Senior 5 min · March 06, 2026

RDS vs DynamoDB — Eventual Consistency Failures at Scale

At 50k writes/sec, DynamoDB returned stale balances.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • RDS: relational, SQL, ACID, vertical scaling, joins, foreign keys
  • DynamoDB: NoSQL, key-value, eventual consistency, horizontal scaling, single-table access patterns
  • Performance: DynamoDB offers single-digit millisecond latency at any scale; RDS latency increases with table joins and index depth
  • Production insight: WRONG choice leads to 10x cost overruns or impossible schema migrations mid-project
  • Biggest mistake: putting relational data (orders, invoices) into DynamoDB and forcing complex joins in app code
Plain-English First

Think of RDS like a giant spreadsheet where every row must follow strict column rules — you can't just add a random extra column to one row without updating the whole sheet. DynamoDB is more like a folder of sticky notes — each note can have completely different information on it, and you can find any note almost instantly because they're all sorted by a label you chose. One is rigid and relational, the other is flexible and blazing fast. The trick is knowing which one your app actually needs.

Every application needs somewhere to store data. But the database decision you make on day one can haunt you for years — choosing the wrong engine means rewriting queries, hitting performance walls, or paying five times more in cloud costs than you should. AWS gives you two wildly different database philosophies under one roof: RDS (Relational Database Service) and DynamoDB. Understanding the difference isn't just academic — it directly affects how fast your app scales, how much it costs, and how easy it is to maintain when traffic triples overnight.

RDS solves the problem of structured, relationship-heavy data. Your users table needs to join your orders table, which joins your products table — and you need those JOINs to be consistent, transactional, and correct. DynamoDB solves a completely different problem: massive throughput at predictable latency. When you're storing session tokens, IoT sensor readings, or user activity events where you need single-digit millisecond reads at any scale, DynamoDB is built for exactly that.

By the end of this article you'll be able to provision both services with infrastructure-as-code, write idiomatic queries against each, understand the cost model differences, and — most importantly — make a confident architectural decision when someone in a design review asks 'should we use RDS or DynamoDB for this?'

Data Model: Rigid vs Flexible

RDS requires a fixed schema. Every table has defined columns with data types, constraints, and relationships enforced via foreign keys. That's great when your data actually fits a relational model — invoices have line items, users have addresses. But it's painful when you need to add a new attribute to a subset of rows: you either add a nullable column or create a separate extension table.

DynamoDB has no schema constraints (except a required partition key and optional sort key). Items in the same table can have completely different attributes. You can add a new field to one item without touching existing items. That flexibility comes at a cost: no automatic referential integrity, no JOINs, and complex multi-item operations require careful application logic.

The rule: if your data has rich relationships you need to enforce at the database level, pick RDS. If your access patterns are primarily by primary key and you need schema evolution without downtime, DynamoDB wins.

Production Insight
A common mistake is putting highly relational data (user profiles with nested preferences and friends) into DynamoDB and trying to simulate joins via multiple API calls.
That pattern breaks under load — each extra read doubles latency and costs.
If you need relational semantics, stay with RDS.
Key Takeaway
RDS for rigid structure and relationships.
DynamoDB for flexible schema and key-value lookups.
Choose based on access patterns, not hype.

Query Capabilities: SQL vs Key-Value

RDS supports full SQL: SELECT with JOINs, WHERE clauses on any column, GROUP BY, aggregations, subqueries, window functions. You can ask complex analytical questions in a single query. DynamoDB supports only three operations on data: GetItem (by primary key), Query (by partition key + optional sort key conditions), and Scan (full table, expensive). Every other filter must be applied on the client side after retrieving the data.

That means DynamoDB forces you to design your access patterns before you write code. You can't spontaneously run a query to find all users who signed up in March and have at least three orders. You'd need a secondary index (GSI) specifically designed for that query, which adds complexity and cost.

Production reality: most teams adopting DynamoDB underestimate how much their query needs will evolve. They end up adding GSIs, creating materialized views, or streaming to a search engine. The trade-off is predictable performance at scale versus ad-hoc query flexibility.

Production Insight
Adding a new reporting requirement after DynamoDB is in production can trigger a week-long migration to create GSIs and backfill data.
With RDS, you just write a new SQL query.
Don't underestimate the cost of schema on write vs schema on read.
Key Takeaway
RDS: ad-hoc queries, JOINs, aggregation.
DynamoDB: pre-defined query patterns, no JOINs.
Plan your access patterns before choosing DynamoDB.

Scaling: Vertical vs Horizontal

RDS scales vertically — you upgrade the instance size (db.r5.large -> db.r5.xlarge) with some downtime. Read-heavy workloads use read replicas (up to 15 for Aurora). Write scaling is harder: you can't shard writes automatically (unless you implement application-level sharding or use Aurora Serverless v2).

DynamoDB scales horizontally from day one. Each partition key can handle 3000 RCU / 1000 WCU. If you exceed that, DynamoDB splits partitions automatically — but only if your partition key is well-distributed. A hot partition key (e.g., a single tenant that gets 90% of traffic) will throttle regardless of total table capacity.

The scaling axis decision is critical. If you expect unpredictable write spikes (e.g., Black Friday), DynamoDB's on-demand auto-scaling is a huge win. If you need complex transactional writes across multiple tables (e.g., inventory deduction + order creation), RDS's single-writer architecture with ACID is simpler to reason about.

Production Insight
A popular e-commerce site used DynamoDB for its product catalogue. During a flash sale, a single product (hot partition key) hit 10,000 writes/second — DynamoDB throttled all writes to that item, causing order failures.
They fixed it by adding a tenant-level partition key prefix.
Key Takeaway
DynamoDB scales horizontally but demands a good partition key.
RDS scales vertically and with read replicas but has a write bottleneck.
Match scaling model to your workload's read/write ratio and spike pattern.

Performance and Latency

DynamoDB guarantees single-digit millisecond latency for GetItem and Query operations at any scale, as long as your partition key is designed well. Reads served from cache (DAX) can be even faster. RDS latency varies: a simple PK lookup can be 1-5ms, but a complex JOIN with full table scans can be 100ms or more. RDS performance depends on query design, indexes, and instance size.

The key difference: DynamoDB latency is predictable regardless of data size (within partition limits). RDS latency grows with data volume and query complexity. For latency-sensitive applications (user sessions, real-time leaderboards), DynamoDB shines. For analytical queries where 500ms is acceptable, RDS is fine.

Production Insight
A social media app stored user feeds in RDS. As the user base grew, the JOINs to assemble a feed (user + posts + likes + comments) became 200-500ms per request. They moved the feed data to DynamoDB, stored denormalized feed items, and queries dropped to 10ms.
Key Takeaway
DynamoDB for predictable low latency at scale.
RDS for complex queries where latency is secondary to query capability.
If you need both, consider a hybrid approach.

Cost Model: Provisioned vs On-Demand

RDS charges per instance hour + storage + IOPS. You pay for the capacity you provision (even if idle) plus storage costs (GP2, GP3, io1). Reserved instances reduce cost for steady workloads. DynamoDB charges per read/write unit (provisioned or on-demand). On-demand lets you pay per request, ideal for variable workloads. But per-request costs are higher than provisioned for sustained traffic.

A common mistake: underestimating DynamoDB costs for heavy read/write workloads. At scale, a table doing 10,000 writes/second with on-demand pricing can cost over $10,000/month. RDS for similar write throughput would be cheaper with a large instance (e.g., db.r5.12xlarge ~$6,000/month reserved). But RDS can't sustain that write throughput for complex writes involving multiple indexes and triggers.

Key trade-off: DynamoDB costs are directly tied to throughput — you can't have high throughput for cheap. RDS costs are tied to compute — you can get moderate throughput at lower cost, but you hit a vertical scaling ceiling.

Production Insight
A gaming company used DynamoDB on-demand for a leaderboard. Average writes were 100/second, but during tournaments they spiked to 50,000/second. Their monthly bill jumped from $500 to $45,000. They switched to provisioned capacity with auto-scaling and scheduled scaling for tournaments, cutting costs by 60%.
Key Takeaway
DynamoDB: pay per request, expensive at high sustained throughput.
RDS: pay per instance, cheaper at moderate throughput, capped at instance size.
Use DynamoDB on-demand for variable loads, provisioned for steady loads.

When to Use Each: Decision Framework

Here's a practical decision tree: If your data has clear relationships (foreign keys, joins in every query) and you need ACID transactions across multiple entities, choose RDS (specifically Aurora for better performance). If your access patterns are primarily by primary key or a single partition key prefix, you need single-digit millisecond latency at any scale, and you can tolerate eventual consistency (or pay for strong consistency), choose DynamoDB.

If you need both? Use a hybrid: store transactional data (orders, users) in RDS, and operational data (sessions, events, pre-computed aggregates) in DynamoDB. Many production systems do exactly this — the key is not forcing one database to do everything.

There's also a middle ground: Amazon Aurora with MySQL compatibility offers up to 5X throughput of standard MySQL and can handle some key-value patterns with the right index design. Don't ignore it as a compromise if your team is familiar with SQL.

Production Insight
A startup built everything on DynamoDB because they wanted horizontal scalability. Two years later, they needed to generate a financial report that required joining five tables. They couldn't. They ended up streaming data to a Redshift cluster for reporting — an extra operational burden they hadn't planned for.
Key Takeaway
RDS for relationships and complex queries.
DynamoDB for simple access patterns and low latency.
Hybrid is often the right answer.
● Production incidentPOST-MORTEMseverity: high

The switch broke when we hit 50k writes per second

Symptom
During a marketing campaign, user balance queries returning stale data caused support tickets and a temporary freeze on withdrawals.
Assumption
DynamoDB's eventual consistency would be fine because reads could be reconciled later.
Root cause
DynamoDB's default eventual consistency means two reads for the same key can return different values within a second. Financial systems need strong consistency (which DynamoDB offers, but at half the throughput and higher cost). The team didn't enable strongly consistent reads because they didn't understand the trade-off.
Fix
Enabled DynamoDB's ConsistentRead parameter for all balance queries. This doubled read costs and halved throughput, revealing the underlying scaling issue. They then moved to RDS PostgreSQL with read replicas, which provided ACID transactional reads for balance operations and eventual consistency for reporting queries.
Key lesson
  • Match consistency model to the data: financial data needs strong consistency.
  • Don't chase horizontal scalability before verifying your access patterns fit key-value models.
  • Always test with production-scale traffic before committing to a database decision.
Production debug guideSymptom-to-action grid for common production problems4 entries
Symptom · 01
RDS: Slow queries as data grows
Fix
Check EXPLAIN ANALYZE, add missing indexes, review join patterns. Consider read replicas for reporting queries.
Symptom · 02
DynamoDB: High latency on hot keys
Fix
Review partition key design. A single partition key can throttle at 3000 RCU/1000 WCU. Add partition key spreading (e.g., tenant_id + timestamp).
Symptom · 03
RDS: Connection pool exhaustion
Fix
Increase max_connections? No, that hits OS limits. Use PgBouncer or RDS Proxy. Check idle transactions.
Symptom · 04
DynamoDB: Expensive scans instead of queries
Fix
Scans cost whole-table read capacity. Restructure access patterns to use Query with key conditions. Add GSI if needed but watch for eventual consistency delays.
★ Instant Debug Checklist for Database ChoiceWhen you're seeing unexplained slowdowns or cost spikes, run through this quick list before escalating.
Reads returning stale data
Immediate action
Check if you're using DynamoDB with eventual consistency when strong consistency is required
Commands
DynamoDB: Set `ConsistentRead: true` in your API call; RDS: Check transaction isolation level
Check application code for missing read-after-write guarantees
Fix now
For DynamoDB: use StronglyConsistentRead; for RDS: use SERIALIZABLE isolation if needed
Write throughput throttling+
Immediate action
Check CloudWatch metrics for ThrottledWrite events
Commands
aws dynamodb describe-table --table-name your-table --query 'Table.ProvisionedThroughput'
aws ec2 describe-instances --instance-ids your-db-instance --query 'Reservations[0].Instances[0].EbsOptimized'
Fix now
Increase DynamoDB WCU or switch to on-demand; for RDS, scale up instance size or add read replicas
Unexpected high costs+
Immediate action
Check Cost Explorer for database service spend
Commands
aws ce get-cost-and-usage --time-period Start=$(date -d '-30 days' +%Y-%m-%d),End=$(date +%Y-%m-%d) --granularity DAILY --metrics BlendedCost --filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon DynamoDB"]}}'
Check if RDS is running on provisioned IOPS (io1/io2) unnecessarily
Fix now
Switch to Aurora Serverless or DynamoDB on-demand for variable workloads
RDS vs DynamoDB: Key Differences
DimensionRDSDynamoDB
Data ModelRelational (tables, rows, columns)Key-value / document (items with attributes)
SchemaFixed, enforced by DBFlexible, no schema per item
Query LanguageSQL (JOINs, aggregations, subqueries)API calls (GetItem, Query, Scan) — limited filtering
ACID TransactionsFull support (across multiple tables)TransactGetItems/TransactWriteItems (max 25 items)
ScalingVertical (upgrade instance) + read replicasHorizontal (partition key based, auto-scaling)
LatencyVaries with query complexity (1-100ms)Single-digit ms for key queries at any scale
ConsistencyImmediate / ACIDEventual by default; Strongly consistent (costs more)
Cost ModelCompute + storage per hourPer read/write unit + storage per GB
Best ForRelational data, complex queries, reportingLow-latency key-value, high throughput, schema-less data

Key takeaways

1
RDS
relational, ACID, SQL, vertical scaling — use for data with relationships and complex queries
2
DynamoDB
NoSQL, key-value, eventual consistency, horizontal scaling — use for high-throughput key-based access at low latency
3
The biggest mistake is forcing one database to do everything
hybrid architectures are common in production
4
Always design access patterns before choosing a database
DynamoDB punishes unprepared query patterns
5
Cost models differ dramatically
DynamoDB per-request can be cheap or expensive depending on traffic patterns; RDS fixed compute cost is predictable

Common mistakes to avoid

5 patterns
×

Using DynamoDB for complex relational data

Symptom
Application code becomes a mess of manual joins across multiple DynamoDB queries, leading to high latency, high costs, and data inconsistency.
Fix
Use RDS (or Aurora) for data that requires JOINs, transactions, and referential integrity. Only use DynamoDB for data with simple key-based access patterns.
×

Choosing RDS for single-table, high-throughput key-value workloads

Symptom
RDS struggles with millions of simple reads per second. Database connection limits, connection pooling overhead, and read replicas add complexity that negates the simplicity of SQL.
Fix
Use DynamoDB with provisioned throughput for workloads where latency matters more than query flexibility. RDS is not designed for massive key-value access.
×

Super-indexing your DynamoDB table

Symptom
Adding many GSIs (global secondary indexes) increases write costs (each GSI consumes table write capacity) and can cause throttling on heavy writes.
Fix
Design access patterns first, then limit GSIs to what's necessary. Often denormalization can eliminate the need for an index.
×

Ignoring partition key design in DynamoDB

Symptom
Throttling on a single partition key (e.g., using a timestamp as partition key causes all writes to go to one partition).
Fix
Use a high-cardinality attribute as partition key (e.g., user_id, order_id) to distribute traffic evenly. Add a sort key for ordering.
×

Not testing with realistic read/write loads before choosing

Symptom
Post-launch performance problems force an emergency migration that costs weeks of development time and exposes data integrity risks.
Fix
Run load tests with production-like traffic on both services (try DynamoDB on-demand and RDS with appropriate instance). Measure latency, cost, and developer effort before committing.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
When would you choose DynamoDB over RDS for a new application?
Q02SENIOR
Explain the concept of a 'hot partition key' in DynamoDB and how to miti...
Q03SENIOR
What are the trade-offs of using DynamoDB's strongly consistent reads vs...
Q04SENIOR
How would you migrate a portion of an RDS-based application to DynamoDB?
Q05SENIOR
Explain the difference between RDS read replicas and DynamoDB global tab...
Q01 of 05SENIOR

When would you choose DynamoDB over RDS for a new application?

ANSWER
Choose DynamoDB when the data access patterns are known upfront and are primarily key-based (e.g., user sessions, player stats, IoT telemetry). The application must tolerate eventual consistency (or pay for strongly consistent reads). The workload must require horizontal scaling with predictable low latency. Also consider if schema flexibility and zero downtime schema changes are important. Do NOT choose DynamoDB if you need complex queries (JOINs, GROUP BY), ad-hoc reporting, strong consistency across multiple entities (ACID transactions spanning tables), or if your data has natural relationships that the DB should enforce. In those cases, RDS is the right choice.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I use both RDS and DynamoDB in the same application?
02
Which is faster: RDS or DynamoDB?
03
Is DynamoDB cheaper than RDS?
04
Does DynamoDB support ACID transactions?
05
Can I run SQL queries on DynamoDB?
🔥

That's Cloud. Mark it forged?

5 min read · try the examples if you haven't

Previous
AWS Lambda and Serverless
6 / 23 · Cloud
Next
AWS VPC and Networking