Technical
DynamoDB Patterns That Held Up Under a Year of Production Load
I picked DynamoDB over PostgreSQL for my platform a year ago and I have been running production traffic through it ever since. The choice has been validated. The specific patterns I adopted are what made the difference between DynamoDB as a strength and DynamoDB as a liability.
Single-Table Design, Actually
I resisted single-table design for months. It felt weird to store different entity types in the same table. Then I tried it and never went back. One table, good access patterns, no joins, predictable costs.
PK SK Entity
----------------- ------------------ ---------
POST#abc POST#abc Post
POST#abc TAG#python Tag
USER#123 USER#123 User
USER#123 SUB#newsletter SubscriptionPK and SK are the primary key. Different entity types coexist. The access patterns drive the design, not the entity shape.
Access Pattern First
Before designing any DynamoDB schema, I write out every query the app needs:
- Get post by slug
- List posts by publish date
- Get all tags for a post
- List posts for a given tag
- Get user by email
Each query maps to a specific PK/SK shape or a Global Secondary Index. No query, no index.
The Streams Win
DynamoDB Streams let me react to data changes without polling. A new subscriber triggers a welcome email. A new post triggers a search index update. All of it happens in the background, triggered by Lambda, zero extra infrastructure.
What Broke
The one thing that broke: I underestimated the pain of changing access patterns after launch. Adding a new query sometimes requires a new GSI or a data migration. Plan queries before schemas.
The Cost Model
DynamoDB on-demand pricing is predictable. For a content platform with moderate traffic, I pay cents per day. The free tier covers most early-stage apps entirely. Cost scales with actual usage, not allocated capacity.
DynamoDB is not always the right choice. For complex relational queries, stick with Postgres. But for high-scale, key-driven workloads, the patterns above have held up for a full year.
The GSI Discipline
Global Secondary Indexes are powerful and expensive if misused. Every GSI costs storage and write capacity. The discipline: add a GSI when a query pattern requires it, not before. I limit myself to at most three GSIs per table. That constraint forces me to think about access patterns before indexing them.
The Backup and Restore Story
Point-in-time recovery on DynamoDB is a toggle. Turn it on for any table with real data. The cost is trivial. The insurance value is enormous. I had one restoration event this year. It took minutes and cost nothing. Worth every penny of the baseline fee.
For the current pattern guide, see the DynamoDB single-table design documentation.
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