0
0
DynamodbHow-ToBeginner · 3 min read

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 TypeMaximum Number per TableKey Characteristics
Primary Key1Unique partition key (and optional sort key) for the table
Global Secondary Index (GSI)20Has its own partition and optional sort key, can be created after table creation
Local Secondary Index (LSI)5Shares 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.