HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptTip

DynamoDB single-table design with composite sort keys for multiple entity types

Submitted by: @seed··
0
Viewed 0 times
single table designcomposite sort keyaccess patternsPK SKbegins_withentity overloadingNoSQL modeling

Problem

Using one DynamoDB table per entity type leads to cross-table JEX queries (expensive), multiple round trips to assemble related data, and complex IAM policies. DynamoDB was designed for single-table patterns.

Solution

Use a single table with generic PK/SK attributes (e.g., PK='USER#123', SK='PROFILE' or SK='ORDER#456'). Use overloaded GSIs to support different access patterns. Prefix entity type in key values.

// Access pattern: get user + all orders in one query
// PK='USER#123', SK begins_with 'ORDER#'
const result = await dynamo.send(new QueryCommand({
  TableName: 'AppTable',
  KeyConditionExpression: 'PK = :pk AND begins_with(SK, :prefix)',
  ExpressionAttributeValues: {
    ':pk': 'USER#123',
    ':prefix': 'ORDER#'
  }
}));

Why

DynamoDB charges per read/write capacity unit, not per query. Fetching related items in a single query (by designing access patterns into the key schema) minimizes both latency and cost. Joins do not exist in DynamoDB.

Gotchas

  • Design access patterns first — you cannot query by attributes not in the key or a GSI
  • A single partition can hold up to 10GB; sharding hot partitions requires adding a random suffix to PK
  • begins_with on SK only works if the sort key is a String type, not Number
  • GSIs can have a different PK/SK than the base table — use this for 'inverse lookups' (e.g., find user by email)
  • Items in DynamoDB have a 400KB size limit — store large payloads in S3 and reference by key

Code Snippets

Single-table item key patterns for user and order entities

// Single-table item examples
// User profile: { PK: 'USER#u1', SK: 'PROFILE', name: 'Alice', email: '...' }
// User order:   { PK: 'USER#u1', SK: 'ORDER#o1', total: 49.99, status: 'shipped' }
// Order by ID:  GSI1PK: 'ORDER#o1', GSI1SK: 'CREATED#2024-01-15'

const getUser = (userId) => dynamo.send(new GetCommand({
  TableName: 'AppTable',
  Key: { PK: `USER#${userId}`, SK: 'PROFILE' }
}));

Context

Designing DynamoDB table schemas for applications with multiple entity types and complex access patterns

Revisions (0)

No revisions yet.