The Most Polarizing Database in AWS
Bring up DynamoDB at any AWS meetup and you will get one of two reactions. Engineers who have shipped on it correctly will tell you it is the most reliable, fastest, lowest-toil database they have ever run in production. Engineers who shipped on it without understanding it will tell you it is a trap that cost them a quarter of pain and an emergency Postgres migration.
Both are right. DynamoDB is a sharp tool. It rewards teams who plan their access patterns up front and punishes teams who treat it as "Postgres but managed." Here is the honest framework for deciding when it fits.
What DynamoDB Is Actually Good At
DynamoDB is built for one thing: predictable, low-latency key-value and document operations at any scale. Single digit millisecond reads. Auto-scaling writes. Zero operational overhead. Global tables across regions if you want them.
When it shines:
- High-volume, well-defined access patterns. Session storage, user profiles by ID, event logs, leaderboards, IoT data, anything you query by a known key.
- Predictable cost at scale. With on-demand pricing, you pay per request. With provisioned capacity, you can lock in costs for steady workloads. Either way, the math is simple.
- Workloads that need to scale to zero or to massive. A side project pays a few dollars a month. A viral launch handles a thousand-fold spike with zero database tuning.
- Multi-region active-active. Global tables are the easiest cross-region replication story in any database.
We use DynamoDB by default for: session storage, audit logs, multi-tenant tenant metadata, caches that survive restarts, agent memory stores, and almost anything tracked by a known ID.
What DynamoDB Is Actually Bad At
The list of things DynamoDB is bad at is shorter than the list of things it is good at, but the bad ones are dealbreakers if you stumble into them.
Ad hoc queries. If you cannot tell me how you will query the data before you write it, DynamoDB is not the right database. There is no "SELECT * WHERE arbitrary thing" path that does not involve scanning the entire table.
Joins. There is no JOIN. You denormalize. If your data model is naturally relational and the relationships are queried in lots of different directions, you will fight this every day.
Aggregations. SUM, AVG, COUNT across rows are not native. You either pre-aggregate at write time or you stream changes to another store (Athena, OpenSearch, Postgres) for analytics.
Transactional writes across many items. Limited transaction support exists, but it is bounded (currently 100 items, 4MB). Long multi-step transactions are not the model.
Reporting and BI. If your stakeholders want to slice the data five new ways every quarter, DynamoDB will not be the source of those queries. You will end up exporting to a warehouse anyway.
The Decision Framework
Three questions, asked honestly, decide it.
Question 1: Do you know your access patterns?
Sit down and write out every read pattern your application needs. "Get user by ID." "List orders for a tenant in the last 30 days." "Find all sessions for a user that have not expired." Every single one.
If you can write down 5 to 15 access patterns and you are confident you have most of them, DynamoDB is on the table. You can design a single-table model that serves all of them efficiently.
If you cannot, or your patterns are growing every week as you ship features, do not pick DynamoDB. You will spend more time refactoring your table design than shipping features.
Question 2: Are your queries point lookups, or are they search and analytics?
Look at the patterns you wrote down. Categorize each.
- Point lookups by ID: DynamoDB is excellent.
- Lookups by secondary key: DynamoDB handles with global secondary indexes.
- Range queries on a sort key: DynamoDB excels.
- Full text search: DynamoDB does not. Add OpenSearch or use a different primary store.
- Aggregations and analytics: DynamoDB does not. Add a warehouse or use Postgres.
If 80 percent of your patterns are the first three categories, DynamoDB is a fit. If 30 percent are the latter two and they are critical to your product, it is not.
Question 3: How much does your team know about NoSQL data modeling?
DynamoDB single-table design is a real skill. Done well, it is elegant. Done poorly, it is unmaintainable. The learning curve for engineers coming from relational databases is steep.
If your team has shipped on DynamoDB before, you can move fast. If they have not, plan for a learning curve and consider whether your timeline allows for it. Most failed DynamoDB projects we have seen failed because someone treated it as Postgres without rows, learned the hard way, and ran out of runway.
For the broader picture of building production SaaS on AWS without these missteps, see Deploying Next.js on AWS the Right Way in 2026 and Multi-Tenant SaaS on AWS: Tenant Isolation Patterns That Actually Work.
The Single-Table Design Pattern
DynamoDB single-table design is what makes the database work for serious applications. The short version:
You put multiple entity types in the same table, share a primary key (PK) and sort key (SK) structure, and use prefixes to differentiate them.
Example:
- USER#123 / METADATA - the user record
- USER#123 / SESSION#abc - a session for that user
- USER#123 / ORDER#456 - an order for that user
- TENANT#789 / USER#123 - tenant membership
A query for "everything related to user 123" is a single query on PK = "USER#123" that returns the user, their sessions, and their orders. A query for "all users in tenant 789" uses a global secondary index on the inverted key.
When this works, it is incredibly efficient. One query returns a whole logical aggregate. No joins, no N+1.
When it goes wrong, it is because the team did not plan the access patterns up front, started adding entities ad hoc, and ended up with a table that no longer serves any pattern well.
Cost Reality
DynamoDB cost is simple but surprises founders.
On-demand pricing is roughly $1.25 per million write requests, $0.25 per million read requests. For most early SaaS, that is rounding error. A typical product at 100K requests per day costs single dollars per month.
Provisioned capacity is meaningfully cheaper if you have steady load. Reserved capacity adds another 50 to 75 percent discount.
Storage is $0.25 per GB-month. For most application data, this is irrelevant. For event logs and audit data, it adds up.
Backups are extra. Point-in-time recovery is $0.20 per GB-month. On-demand backups are extra storage.
The cost trap is global secondary indexes. Each GSI is effectively a copy of your data filtered by that index, billed for both writes and storage. Three GSIs roughly triples your write cost. Plan accordingly.
For more on keeping AWS spend in check as you scale, see AWS Cost Optimization: 7 Quick Wins That Save Thousands.
When We Use Postgres Instead
For most SaaS workloads, our default is Aurora Postgres or RDS Postgres. Reasons:
- The team already knows SQL
- Access patterns are still evolving
- The product needs to support analytics and reporting
- The data model is naturally relational
- We want JSON columns for the flexible parts and structured columns for the rest
Aurora Serverless v2 has eliminated most of the operational reasons to avoid Postgres in serverless architectures. It scales to zero, it autoscales, and it speaks vanilla Postgres.
When we use DynamoDB, it is usually for a specific subsystem within a Postgres-primary application. Sessions, audit logs, agent memory, real-time event tracking. The right tool for the right job.
A Simple Decision Rule
If your application is mostly CRUD with evolving requirements and a need for reporting, default to Aurora Postgres. Add DynamoDB for specific subsystems where it shines.
If your application is built around a small number of well-known access patterns and you need to scale to high traffic with predictable cost and minimal ops, default to DynamoDB. Add Postgres for the parts that need ad hoc queries.
If you are building both at once and not sure which is primary, build a thin data access layer that hides the choice for the first few weeks. By the time you have shipped enough features to know your access patterns, the right answer will be obvious.
Get a Data Model Review
The most expensive database decisions are the ones you cannot easily reverse. We do focused data model reviews that look at your access patterns, current pain points, and growth plan, and produce a recommendation with a migration path if needed.
If you are at the start of a build and not sure which way to go, or living with a data model that is starting to bite, get in touch. Our SaaS development service handles this kind of architecture work end to end, and you can read more about how we build with a small team in Small Team, Big Architecture.