DynamoDB Index Limits: How Many Indexes Can a Table Have?
A DynamoDB table can have one primary key, up to 20 global secondary indexes (
GSI), and up to 5 local secondary indexes (LSI). These limits define how many indexes you can create per table to optimize your queries.Syntax
When creating or updating a DynamoDB table, you define indexes as part of the table schema. The main types are:
- Primary Key: The main unique identifier for items.
- Global Secondary Index (GSI): An index with its own partition and sort key, can be created up to 20 per table.
- Local Secondary Index (LSI): An index that shares the same partition key as the primary key but has a different sort key, limited to 5 per table.
json
{
"TableName": "ExampleTable",
"KeySchema": [
{ "AttributeName": "UserId", "KeyType": "HASH" },
{ "AttributeName": "OrderId", "KeyType": "RANGE" }
],
"AttributeDefinitions": [
{ "AttributeName": "UserId", "AttributeType": "S" },
{ "AttributeName": "OrderId", "AttributeType": "S" },
{ "AttributeName": "Status", "AttributeType": "S" },
{ "AttributeName": "CreatedAt", "AttributeType": "N" }
],
"LocalSecondaryIndexes": [
{
"IndexName": "StatusIndex",
"KeySchema": [
{ "AttributeName": "UserId", "KeyType": "HASH" },
{ "AttributeName": "Status", "KeyType": "RANGE" }
],
"Projection": { "ProjectionType": "ALL" }
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "CreatedAtIndex",
"KeySchema": [
{ "AttributeName": "CreatedAt", "KeyType": "HASH" }
],
"Projection": { "ProjectionType": "ALL" },
"ProvisionedThroughput": { "ReadCapacityUnits": 5, "WriteCapacityUnits": 5 }
}
],
"ProvisionedThroughput": { "ReadCapacityUnits": 5, "WriteCapacityUnits": 5 }
}Example
This example shows creating a DynamoDB table with 1 primary key, 1 local secondary index, and 1 global secondary index. It demonstrates how to define indexes within the table schema.
javascript
const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB({ region: 'us-east-1' }); const params = { TableName: 'Orders', KeySchema: [ { AttributeName: 'UserId', KeyType: 'HASH' }, { AttributeName: 'OrderId', KeyType: 'RANGE' } ], AttributeDefinitions: [ { AttributeName: 'UserId', AttributeType: 'S' }, { AttributeName: 'OrderId', AttributeType: 'S' }, { AttributeName: 'Status', AttributeType: 'S' }, { AttributeName: 'CreatedAt', AttributeType: 'N' } ], LocalSecondaryIndexes: [ { IndexName: 'StatusIndex', KeySchema: [ { AttributeName: 'UserId', KeyType: 'HASH' }, { AttributeName: 'Status', KeyType: 'RANGE' } ], Projection: { ProjectionType: 'ALL' } } ], GlobalSecondaryIndexes: [ { IndexName: 'CreatedAtIndex', KeySchema: [ { AttributeName: 'CreatedAt', KeyType: 'HASH' } ], Projection: { ProjectionType: 'ALL' }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } } ], ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } }; dynamodb.createTable(params, (err, data) => { if (err) { console.error('Error creating table:', err); } else { console.log('Table created successfully:', data.TableDescription.TableName); } });
Output
Table created successfully: Orders
Common Pitfalls
Many developers try to create more than 20 global secondary indexes or more than 5 local secondary indexes on a single DynamoDB table, which is not allowed and causes errors.
Also, local secondary indexes must share the same partition key as the primary key, but have a different sort key. Trying to define an LSI with a different partition key will fail.
Remember that each index adds cost and complexity, so only create indexes you really need.
javascript
/* Wrong: Trying to create 21 GSIs (exceeds limit) */ const tooManyGSIs = new Array(21).fill(null).map((_, i) => ({ IndexName: `GSI${i+1}`, KeySchema: [ { AttributeName: 'GSIKey', KeyType: 'HASH' } ], Projection: { ProjectionType: 'ALL' }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } })); /* Right: Limit GSIs to 20 or fewer */ const validGSIs = new Array(20).fill(null).map((_, i) => ({ IndexName: `GSI${i+1}`, KeySchema: [ { AttributeName: 'GSIKey', KeyType: 'HASH' } ], Projection: { ProjectionType: 'ALL' }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } }));
Quick Reference
| Index Type | Maximum Number per Table | Key Characteristics |
|---|---|---|
| Primary Key | 1 | Unique partition key (and optional sort key) for the table |
| Global Secondary Index (GSI) | 20 | Has its own partition and optional sort key, can be created after table creation |
| Local Secondary Index (LSI) | 5 | Shares the same partition key as primary key but has a different sort key, must be created at table creation |
Key Takeaways
A DynamoDB table supports 1 primary key, up to 20 global secondary indexes, and up to 5 local secondary indexes.
Local secondary indexes must share the same partition key as the primary key but have a different sort key.
Global secondary indexes have their own partition and sort keys and can be added after table creation.
Exceeding index limits causes errors and should be avoided.
Indexes improve query flexibility but add cost and complexity, so use them wisely.