Technical
DynamoDB Single-Table Design for Beginners
DynamoDB looks intimidating at first. One table with generic partition keys, sort keys that look like encoded strings, no joins. Coming from SQL, it feels wrong. It is not wrong. It is a different model optimized for different constraints. Here is how I think about it.
The Core Insight
In SQL, you design the schema around the data. In DynamoDB, you design the schema around the access patterns. Before writing a single line of schema, you list every query the app will run. Then you pick keys that make those queries cheap.
The Table Structure
One table. A partition key called pk and a sort key called sk. Everything else is a regular attribute.
Table: main
pk (partition key): string
sk (sort key): string
GSI1pk, GSI1sk: optional secondary indexThat is the whole schema. The magic is in how you encode entity types into pk and sk.
Example: Users and Orders
A user has many orders. In SQL, that is two tables with a foreign key. In DynamoDB, it is two item types in the same table:
pk | sk | attributes
USER#123 | METADATA | name, email
USER#123 | ORDER#2025-06-01| amount, items
USER#123 | ORDER#2025-06-02| amount, itemsTo get a user and their orders in one query: query where pk = 'USER#123'. You get the metadata row plus all order rows in a single call. No joins. No N+1 queries.
Access Patterns Drive Design
List my access patterns first:
- Get user by ID
- List all orders for a user
- Get specific order by user and date
All three are served by the same pk = USER#id structure. Different sort-key prefixes narrow the result set.
When to Use a GSI
Global Secondary Indexes let you query on attributes other than the main partition key. If I need 'find all orders over $100,' I add a GSI where GSI1pk = OVER_100 and GSI1sk = amount. Only rows that match get indexed. The GSI is cheap.
Common Mistakes
- Using DynamoDB like SQL: creating one table per entity type. You lose the single-query benefit.
- Designing the schema before listing access patterns: you will index the wrong things.
- Fighting the model: DynamoDB is not a bad SQL database. It is a good key-value database with some relational features bolted on.
Cost Reality
The free tier covers 25GB of storage, 25 read capacity units, and 25 write capacity units. That is enough for every side project I have ever built. You pay when you scale, not when you start.
See the DynamoDB developer guide and the single-table design patterns article for deeper patterns.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read