NoSQL Databases

DynamoDB Single-Table Design: Access Patterns, GSIs, and Capacity Planning

Model DynamoDB data with single-table design. Covers composite sort keys, GSI design for multiple access patterns, and on-demand vs provisioned capacity.

JusDB Team
June 13, 2025
5 min read
161 views

DynamoDB's single-table design pattern enables high performance at scale, but requires rethinking how you model data compared to relational databases.

Core Concepts

  • Partition Key (PK): distributes data across nodes — must be high cardinality
  • Sort Key (SK): enables range queries within a partition
  • GSI: Global Secondary Index — alternate access patterns with different PK/SK
  • LSI: Local Secondary Index — alternate SK, same PK (must be defined at table creation)

Single-Table Design

text
PK              SK               Attributes
USER#123        PROFILE          name, email, created_at
USER#123        ORDER#2025-001   amount, status
USER#123        ORDER#2025-002   amount, status
ORDER#2025-001  ITEM#prod-A      quantity, price
ORDER#2025-001  ITEM#prod-B      quantity, price

One table holds users, orders, and order items. Access patterns map directly to PK/SK queries.

Common Access Patterns

python
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('MyTable')

# Get user profile
table.get_item(Key={'PK': 'USER#123', 'SK': 'PROFILE'})

# Get all orders for user (SK begins_with)
table.query(
    KeyConditionExpression='PK = :pk AND begins_with(SK, :prefix)',
    ExpressionAttributeValues={':pk': 'USER#123', ':prefix': 'ORDER#'}
)

# Get specific order
table.get_item(Key={'PK': 'USER#123', 'SK': 'ORDER#2025-001'})

Global Secondary Index for Reverse Lookup

json
{
  "GlobalSecondaryIndexes": [{
    "IndexName": "GSI1",
    "KeySchema": [
      {"AttributeName": "GSI1PK", "KeyType": "HASH"},
      {"AttributeName": "GSI1SK", "KeyType": "RANGE"}
    ],
    "Projection": {"ProjectionType": "ALL"}
  }]
}
text
GSI1PK            GSI1SK         Use case
STATUS#pending    ORDER#2025-001  All pending orders
EMAIL#user@ex.com USER#123       User lookup by email

Capacity Planning

  • On-demand: no planning needed, pay per request — best for variable/unpredictable traffic
  • Provisioned + Auto Scaling: set min/max RCU/WCU — better for steady predictable load
bash
# Monitor consumed capacity
aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ConsumedReadCapacityUnits \
  --dimensions Name=TableName,Value=MyTable \
  --statistics Sum --period 60

Key Takeaways

  • Single-table design puts all entity types in one table — access patterns drive schema
  • Use composite SK values (ORDER#2025-001) to enable range queries within a partition
  • GSIs add access patterns — plan them up front since GSI data is eventually consistent
  • Use on-demand capacity for new applications; switch to provisioned + auto scaling after load stabilizes

JusDB Can Help

DynamoDB single-table design requires up-front access pattern analysis. JusDB can model your data for DynamoDB and avoid costly re-migrations.

Share this article

JusDB Team

Official JusDB content team