AWS DynamoDB: Advanced Patterns for Production at Scale

AWS DynamoDB: Advanced Patterns for Production at Scale

DynamoDB mistakes are expensive — not in dollars, but in the hot partitions, full table scans, and impossible access patterns that result from wrong key design. The advanced patterns here — single-table design, GSI overloading, sparse indexes, and conditional writes — are what power the highest-scale production DynamoDB systems.

TL;DR: Design access patterns first, then choose keys. Single-table: prefix PK/SK for different entity types. GSI for alternate access patterns. Sparse GSI: only items with GSI attribute are indexed. Conditional writes for optimistic locking. DynamoDB Streams trigger Lambda on changes. TTL for automatic expiry.

Single-table design patterns

// All entities in one table: prefix PK and SK
// Users and orders in same table:
// PK: USER#userId        SK: METADATA          → user entity
// PK: USER#userId        SK: ORDER#orderId      → user's order
// PK: ORDER#orderId      SK: METADATA          → order entity
// PK: ORDER#orderId      SK: ITEM#itemId        → order item

// Query all orders for a user:
const result = await client.send(new QueryCommand({
  TableName: 'main',
  KeyConditionExpression: 'PK = :pk AND begins_with(SK, :prefix)',
  ExpressionAttributeValues: {
    ':pk': 'USER#'+userId,
    ':prefix': 'ORDER#'
  }
}));

// Query single order:
const order = await client.send(new GetItemCommand({
  TableName: 'main',
  Key: { PK: 'ORDER#'+orderId, SK: 'METADATA' }
}));

GSI overloading — multiple access patterns from one GSI

// GSI1: GSI1PK, GSI1SK — overloaded for different entity types

// User entity:
// PK: USER#123   SK: METADATA
// GSI1PK: EMAIL#alice@example.com  GSI1SK: USER#123
// → GSI1 enables: look up user by email

// Order entity:
// PK: ORDER#456  SK: METADATA
// GSI1PK: STATUS#pending            GSI1SK: DATE#2026-04-01
// → GSI1 enables: query all pending orders by date

// Same GSI serves completely different entity lookups!
// Key: different entities use different value formats in GSI1PK

Conditional writes — optimistic locking

// Only update if version matches (prevents lost updates)
const updateResult = await client.send(new UpdateItemCommand({
  TableName: 'inventory',
  Key: { PK: 'PRODUCT#'+productId, SK: 'STOCK' },
  UpdateExpression: 'SET stock = stock - :qty, version = version + :one',
  ConditionExpression: 'stock >= :qty AND version = :v',
  ExpressionAttributeValues: {
    ':qty': { N: '1' }, ':one': { N: '1' }, ':v': { N: String(currentVersion) }
  }
}));
// If stock < qty or version changed: ConditionalCheckFailedException
// Retry with fresh version if optimistic lock fails

DynamoDB Transactions + TTL

// ACID transactions across up to 25 items:
await client.send(new TransactWriteItemsCommand({
  TransactItems: [
    { Update: { // Debit account
      TableName:'accounts', Key:{PK:'ACCT#from'},
      UpdateExpression:'SET balance = balance - :amt',
      ConditionExpression:'balance >= :amt',
      ExpressionAttributeValues:{':amt':{N:'100'}}
    }},
    { Update: { // Credit account
      TableName:'accounts', Key:{PK:'ACCT#to'},
      UpdateExpression:'SET balance = balance + :amt',
      ExpressionAttributeValues:{':amt':{N:'100'}}
    }}
  ]
}));

// TTL: auto-delete expired items (free!)
// Store TTL as Unix timestamp in 'expiresAt' attribute
// Enable TTL: aws dynamodb update-time-to-live --ttl-attribute expiresAt
  • ✅ Single-table design for related entities with multiple access patterns
  • ✅ GSI overloading: one GSI serves multiple entity lookup patterns
  • ✅ Conditional writes for optimistic concurrency control
  • ✅ TTL for automatic session/cache/token expiry
  • ✅ Transactions for atomic multi-item updates
  • ❌ Never start with DynamoDB before identifying access patterns
  • ❌ Never scan large tables — redesign keys instead

External reference: Alex DeBrie Single-Table Design.

Recommended Reading

Designing Data-Intensive Applications — The bible of distributed systems and production engineering at scale.

The Pragmatic Programmer — Timeless engineering wisdom every senior developer needs.

Affiliate links. We earn a small commission at no extra cost to you.

Free Weekly Newsletter

🚀 Join 2,000+ Senior Developers

Get expert-level JavaScript, Python, AWS, system design and AI secrets every week. Zero fluff, pure signal.

✓ No spam✓ Unsubscribe anytime✓ Expert-level only

Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply