A Global Secondary Index (GSI) lets you search your DynamoDB table using different keys than the main one. It helps you find data faster in new ways.
Creating GSI in DynamoDB
CreateTable {
TableName: string,
KeySchema: [
{ AttributeName: string, KeyType: 'HASH' | 'RANGE' }
],
AttributeDefinitions: [
{ AttributeName: string, AttributeType: 'S' | 'N' | 'B' }
],
GlobalSecondaryIndexes: [
{
IndexName: string,
KeySchema: [
{ AttributeName: string, KeyType: 'HASH' | 'RANGE' }
],
Projection: {
ProjectionType: 'ALL' | 'KEYS_ONLY' | 'INCLUDE',
NonKeyAttributes?: [string]
},
ProvisionedThroughput: {
ReadCapacityUnits: number,
WriteCapacityUnits: number
}
}
],
ProvisionedThroughput: {
ReadCapacityUnits: number,
WriteCapacityUnits: number
}
}The GlobalSecondaryIndexes section defines one or more GSIs.
Each GSI needs its own IndexName, KeySchema, and Projection to specify what data it holds.
GlobalSecondaryIndexes: [
{
IndexName: 'GSI1',
KeySchema: [
{ AttributeName: 'Category', KeyType: 'HASH' }
],
Projection: { ProjectionType: 'ALL' },
ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 }
}
]GlobalSecondaryIndexes: [
{
IndexName: 'GSI2',
KeySchema: [
{ AttributeName: 'Status', KeyType: 'HASH' },
{ AttributeName: 'CreatedDate', KeyType: 'RANGE' }
],
Projection: { ProjectionType: 'INCLUDE', NonKeyAttributes: ['Description', 'Priority'] },
ProvisionedThroughput: { ReadCapacityUnits: 10, WriteCapacityUnits: 5 }
}
]This command creates a DynamoDB table named 'Products' with a primary key 'ProductId'. It also creates a GSI called 'CategoryIndex' that lets you query products by their 'Category'.
aws dynamodb create-table \
--table-name Products \
--attribute-definitions \
AttributeName=ProductId,AttributeType=S \
AttributeName=Category,AttributeType=S \
--key-schema AttributeName=ProductId,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
'[{
"IndexName": "CategoryIndex",
"KeySchema": [{"AttributeName":"Category","KeyType":"HASH"}],
"Projection": {"ProjectionType":"ALL"},
"ProvisionedThroughput": {"ReadCapacityUnits":5,"WriteCapacityUnits":5}
}]'GSIs let you query your data in new ways without changing your main table keys.
Remember to define the attributes used in your GSI in AttributeDefinitions.
Provisioned throughput for GSIs is separate from the main table and affects cost.
GSIs let you search your DynamoDB table using different keys.
They require defining new key schemas and projections.
Use GSIs to add flexible query options without rebuilding your table.
Practice
Solution
Step 1: Understand what a GSI does
A GSI lets you query a DynamoDB table using different key attributes than the primary key.Step 2: Compare options to GSI purpose
Options A, B, and D describe backup, storage, and encryption, which are unrelated to GSI functionality.Final Answer:
To allow querying the table using alternative key attributes -> Option CQuick Check:
GSI = alternative query keys [OK]
- Thinking GSI increases storage size
- Confusing GSI with backup or encryption features
- Assuming GSI changes the primary key
OrderDateIndex with OrderDate as the partition key in a DynamoDB table creation JSON?Solution
Step 1: Identify correct KeyType for partition key in GSI
The partition key in DynamoDB GSI uses KeyType "HASH".Step 2: Check options for correct KeyType and syntax
"GlobalSecondaryIndexes": [{"IndexName": "OrderDateIndex", "KeySchema": [{"AttributeName": "OrderDate", "KeyType": "HASH"}], "Projection": {"ProjectionType": "ALL"}}] uses "HASH" correctly; B uses "RANGE" (wrong for partition key), C uses invalid "PRIMARY", D uses invalid "PARTITION".Final Answer:
"GlobalSecondaryIndexes": [{"IndexName": "OrderDateIndex", "KeySchema": [{"AttributeName": "OrderDate", "KeyType": "HASH"}], "Projection": {"ProjectionType": "ALL"}}] -> Option AQuick Check:
Partition key = HASH [OK]
- Using 'RANGE' instead of 'HASH' for partition key
- Using invalid KeyType values like 'PRIMARY' or 'PARTITION'
- Forgetting to define ProjectionType
UserEmailIndex where Email is the partition key, what will be the result of this query?QueryInput = {
TableName: "Users",
IndexName: "UserEmailIndex",
KeyConditionExpression: "Email = :email",
ExpressionAttributeValues: {":email": "alice@example.com"}
}Solution
Step 1: Understand QueryInput with IndexName
Specifying IndexName in QueryInput tells DynamoDB to query the GSI instead of the main table.Step 2: Analyze KeyConditionExpression
The query filters items where Email equals 'alice@example.com' on the GSI partition key.Final Answer:
Returns all items where Email attribute equals 'alice@example.com' using the GSI -> Option AQuick Check:
Query with IndexName uses GSI keys [OK]
- Assuming query uses main table keys when IndexName is set
- Thinking IndexName causes error in QueryInput
- Ignoring KeyConditionExpression filtering
"GlobalSecondaryIndexes": [{
"IndexName": "StatusIndex",
"KeySchema": [{"AttributeName": "Status", "KeyType": "HASH"}],
"Projection": {"ProjectionType": "INCLUDE", "NonKeyAttributes": []}
}]What is the likely cause of the error?
Solution
Step 1: Check ProjectionType and NonKeyAttributes
When ProjectionType is INCLUDE, NonKeyAttributes must be a non-empty array listing attributes to project.Step 2: Verify given snippet
NonKeyAttributes is [], which is empty and invalid when ProjectionType is INCLUDE.Step 3: Eliminate other options
ProjectionType INCLUDE is valid; KeyType HASH is valid for partition key; IndexName can contain 'Index'.Final Answer:
NonKeyAttributes must be a non-empty array when ProjectionType is INCLUDE -> Option BQuick Check:
INCLUDE projection requires NonKeyAttributes [OK]
- Using empty or missing NonKeyAttributes with INCLUDE
- Confusing KeyType HASH and RANGE for partition key
- Thinking IndexName naming causes errors
UserID. You want to query users by their City and SignupDate. Which GSI definition allows efficient queries for all users in a city sorted by signup date?Solution
Step 1: Identify partition and sort keys for query pattern
To query all users in a city sorted by signup date, City should be the partition key (HASH) and SignupDate the sort key (RANGE).Step 2: Check options for correct KeySchema order
"GlobalSecondaryIndexes": [{"IndexName": "CitySignupIndex", "KeySchema": [{"AttributeName": "City", "KeyType": "HASH"}, {"AttributeName": "SignupDate", "KeyType": "RANGE"}], "Projection": {"ProjectionType": "ALL"}}] correctly sets City as HASH and SignupDate as RANGE. Options B and C swap keys incorrectly. "GlobalSecondaryIndexes": [{"IndexName": "CitySignupIndex", "KeySchema": [{"AttributeName": "SignupDate", "KeyType": "RANGE"}], "Projection": {"ProjectionType": "ALL"}}] lacks partition key.Final Answer:
"GlobalSecondaryIndexes": [{"IndexName": "CitySignupIndex", "KeySchema": [{"AttributeName": "City", "KeyType": "HASH"}, {"AttributeName": "SignupDate", "KeyType": "RANGE"}], "Projection": {"ProjectionType": "ALL"}}] -> Option DQuick Check:
Partition key = City, Sort key = SignupDate [OK]
- Swapping HASH and RANGE keys
- Missing partition key in GSI
- Using only one key when two are needed for sorting
Ready to prove it?
Pass the test and this pattern moves unknown
