What is single-table design in DynamoDB and why is it recommended?
Learn what single-table design in DynamoDB is, how key overloading and GSIs pre-join data, why it cuts requests and cost, and when to use it — with examples.
Expected Interview Answer
Single-table design is a DynamoDB modeling approach where multiple entity types (users, orders, products) are stored in one table and distinguished by carefully crafted partition and sort key values, so that related items sit together and common access patterns are served by a single query.
Because DynamoDB has no server-side joins, spreading entities across many tables forces multiple round trips to assemble one view. Single-table design instead pre-joins data by placing related items under the same partition key with structured sort keys (e.g. USER#123 as PK, PROFILE or ORDER#456 as SK), and uses generic key names plus Global Secondary Indexes to reshape access. This lets one Query return a user and all their orders together, minimizing requests and cost. It is recommended when access patterns are known up front and latency and throughput matter more than modeling convenience.
- Fewer round trips — related items fetched in one Query
- Lower cost by reducing request count and avoiding joins
- Consistent single-digit millisecond latency at scale
- Supports transactions across entities in one table
- Fewer tables to provision, monitor and secure
AI Mentor Explanation
Think of one master scorebook that holds everything about a match on shared pages: partnerships, bowling figures, and fall-of-wickets all filed under the same match ID and ordered by over. Instead of flipping between separate books for batting, bowling and fielding, a scorer opens to that match ID once and reads the whole story in order. Single-table design files every related entity under one key so one lookup returns the full picture.
Step-by-Step Explanation
Step 1
Enumerate access patterns
List every read and write your application performs first — DynamoDB modeling is access-pattern driven, not entity driven.
Step 2
Choose generic key names
Name the keys PK and SK (and index keys GSI1PK/GSI1SK) so different entity types can overlay the same attributes.
Step 3
Design key values per entity
Encode entity type and identity into keys, e.g. PK=USER#123, SK=PROFILE or SK=ORDER#456, so related items share a partition.
Step 4
Add GSIs for other patterns
Create Global Secondary Indexes with overloaded keys to serve access patterns the base table keys cannot, such as querying orders by status.
Step 5
Validate each pattern maps to one query
Confirm every access pattern is satisfied by a single Query or GetItem, not a Scan, before finalizing the schema.
What Interviewer Expects
- Understanding that DynamoDB has no joins, driving pre-joining of data
- Access-pattern-first modeling rather than normalized entity modeling
- Composite and overloaded key design (PK/SK, entity prefixes)
- Knowledge of GSIs and key overloading to serve extra patterns
- Awareness of the trade-offs versus multi-table design
Common Mistakes
- Modeling normalized relational tables and expecting joins to work
- Designing entities before enumerating access patterns
- Using Scan to compensate for a schema that does not fit the queries
- Ignoring hot partitions from poorly distributed partition keys
- Claiming single-table is always correct even for unknown access patterns
Best Answer (HR Friendly)
“Single-table design means keeping many kinds of related data in one DynamoDB table and labeling each row with clever keys so related things sit next to each other. That way the app can grab everything it needs, like a customer and all their orders, in a single fast request instead of many.”
Code Example
// One table holds users AND orders, distinguished by key values
// User item: { PK: 'USER#123', SK: 'PROFILE', name: 'Ada' }
// Order item: { PK: 'USER#123', SK: 'ORDER#2026-01', total: 90 }
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb'
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}))
// Fetch the user profile AND all their orders in ONE query
const res = await ddb.send(new QueryCommand({
TableName: 'AppTable',
KeyConditionExpression: 'PK = :pk',
ExpressionAttributeValues: { ':pk': 'USER#123' },
}))
const profile = res.Items.find((i) => i.SK === 'PROFILE')
const orders = res.Items.filter((i) => i.SK.startsWith('ORDER#'))Follow-up Questions
- When is multi-table design actually the better choice?
- What is key overloading and how do GSIs use it?
- How do you avoid hot partitions in a single-table design?
- How do DynamoDB transactions work across entities in one table?
- How does single-table design complicate analytics and ad-hoc queries?
MCQ Practice
1. Why does single-table design reduce request count in DynamoDB?
DynamoDB has no joins; placing related items under one partition key lets a single Query fetch them in one request.
2. What primarily drives the schema in single-table design?
DynamoDB modeling starts from enumerating access patterns, then designs keys so each pattern maps to one Query or GetItem.
3. What technique lets different entity types share the same index keys?
Key overloading reuses generic key attributes (like GSI1PK) with different value patterns per entity to serve multiple access patterns.
Flash Cards
What is single-table design? — Storing multiple entity types in one DynamoDB table, distinguished by composite key values, so related items are pre-joined under shared partitions.
Why no joins in DynamoDB? — DynamoDB is a distributed NoSQL store; joins would require cross-partition coordination, so data is instead pre-joined at write time via key design.
What is key overloading? — Using generic key attributes (PK/SK, GSI1PK) with entity-specific value patterns so one index serves many access patterns.
When avoid single-table design? — When access patterns are unknown or evolving, or when analytics/ad-hoc queries dominate — flexibility then outweighs request efficiency.