AWS Database Services: How Do You Choose Between RDS, Aurora, DynamoDB, and Neptune?
From relational databases to graph and time-series stores, learn what problem each AWS database service—RDS, Aurora, DynamoDB, ElastiCache, Neptune, DocumentDB, Keyspaces, and Timestream—actually solves, and when you should reach for it.
First, split the world into two camps: relational and NoSQL
Before diving into individual services, you need a rough map of the landscape.
Relational databases store data in tables with a fixed schema, link those tables together with foreign keys, and support SQL for cross-table queries and transactions that guarantee consistency. Their strength is data integrity and complex queries—the tradeoff is that vertical scaling eventually runs into the physical limits of a single machine.
NoSQL databases deliberately give up table relationships in exchange for more flexible data structures and architectures that scale horizontally more easily. But NoSQL isn't one technology—it's a whole family, with sub-models like key-value, document, graph, and wide-column stores underneath it.
RDS and Aurora belong to the relational camp. DynamoDB, DocumentDB, Neptune, and Keyspaces belong to the NoSQL camp.
RDS: hand your everyday relational database off to AWS
RDS (Relational Database Service) solves the most basic problem: you want to use a familiar relational database like MySQL or PostgreSQL, but you don't want to deal with installation, patching, backups, and failover yourself.
At its core, RDS manages an off-the-shelf database engine for you, with options including MySQL, PostgreSQL, MariaDB, Oracle, and SQL Server. You just pick the engine and the instance size—AWS handles automated backups and Multi-AZ failover from there.
It's a good fit when you already have an application built on one of these engines and just don't want to run the ops yourself, or when you need the existing ecosystem around a specific engine like Oracle or SQL Server. But RDS is still that underlying database engine—performance and scaling headroom are roughly the same as the open-source version.
Aurora: AWS's own high-performance relational engine
If you're running MySQL or PostgreSQL but want better performance and scalability than the open-source versions offer, that's where Aurora comes in. The key difference from RDS is that Aurora doesn't just manage the open-source engine—AWS rewrote the storage layer itself, separating compute from storage. That storage layer automatically replicates data six ways across multiple Availability Zones, and AWS claims performance up to five times standard MySQL and three times standard PostgreSQL.
From your application's perspective, Aurora is wire-compatible with MySQL and PostgreSQL, so code written against either engine connects to Aurora with barely any changes. It also offers Aurora Serverless, which scales compute capacity up and down automatically based on load—a good fit when traffic is spiky and you don't want to size instances by hand.
Think of Aurora as the premium version of RDS. If you're already committed to MySQL or PostgreSQL, Aurora is the better default in most cases—the main tradeoff is cost, since that extra performance doesn't come free.
DynamoDB: a key-value/document database that frees you from capacity planning
The two services above are still relational. DynamoDB is a completely different animal: a fully managed NoSQL database that stores data as key-value pairs or documents, with no fixed schema and no cross-table joins.
Its standout feature is unlimited capacity with consistent single-digit-millisecond latency, and it's a genuinely serverless architecture—unlike RDS, you don't have to pick an instance size upfront; it scales automatically as read/write traffic grows.
DynamoDB shines when your query patterns are simple but traffic is massive—shopping carts in e-commerce, player state in games, session data in mobile apps. The tradeoff is query flexibility: it's nowhere near SQL, and complex multi-field filters or cross-entity queries are much harder to pull off than in a relational database. That's exactly why designing a DynamoDB table means figuring out your access patterns first, instead of starting from the data model the way you would with a relational database.
ElastiCache: putting hot data in memory for speed
Whether it's RDS, Aurora, or DynamoDB, the data ultimately lives on disk (persistent storage), and no matter how fast that read is, it still can't beat pulling data straight from memory. ElastiCache solves exactly this problem: it's a fully managed in-memory data store supporting both Redis and Memcached, caching data that's read often but changes rarely, and bringing read latency down to microseconds.
The typical pattern sits it in front of the database as a cache layer: your app checks ElastiCache first, returns immediately on a cache hit, and only falls back to RDS or DynamoDB on a miss—then writes the result back into the cache. Since Redis also supports richer data structures (lists, sets, sorted sets) and pub/sub, it's often used for more than caching alone—leaderboards, real-time notifications, and shared sessions are all common use cases.
Keep in mind that ElastiCache is fundamentally a cache, not a primary data store—data can disappear due to memory pressure or an instance restart. Design your architecture assuming the cache can be empty at any moment; don't treat it as a replacement for a real database.
DocumentDB: a document database compatible with the MongoDB protocol
If your team is already comfortable with MongoDB's document model—storing data as JSON documents—but you'd rather have AWS manage the cluster than run it yourself, DocumentDB is the answer. It's compatible with the MongoDB API, so existing code written against a MongoDB driver connects with barely any changes.
DocumentDB and DynamoDB are both NoSQL, but they fit different scenarios. DynamoDB leans toward high-throughput workloads with simple query patterns, while DocumentDB keeps the document model's richer data shapes—nested structures, arrays—making it a better fit when your data is moderately complex but not complex enough to need relational tables. Think CMS article content or user personalization profiles.
Neptune: a graph database built for relationships themselves
Every service so far answers the question of how to store individual records. But some problems aren't really about individual records at all—they're about the relationships between them: who follows whom on a social network, product recommendations on an e-commerce site, suspicious links between accounts in fraud detection. Force these through multi-level joins in a relational database, and performance falls off a cliff as the relationship depth grows.
Neptune is a graph database built exactly for this: it stores data as nodes and edges, where the edges themselves represent relationships. Querying something like "what has this user's friend's friend bought" runs far faster than the equivalent multi-level join on a relational database. It supports Gremlin, SPARQL, and openCypher as query languages, making it a natural fit for social graphs, knowledge graphs, recommendation engines, and fraud-detection networks—anywhere the relationship is the point.
Keyspaces: a wide-column database compatible with Cassandra
Keyspaces (for Apache Cassandra) is another NoSQL branch, using a wide-column data model: think of a table where each row can have a different set of columns, unlike a traditional relational table where every row shares the same fixed columns. It's compatible with open-source Cassandra's CQL (Cassandra Query Language), so teams already running Cassandra can migrate over with almost no friction, in exchange for a fully managed, cluster-free operational model.
The wide-column model is especially suited to extremely high write volumes with low-latency reads and writes across geographic regions—think IoT sensor data or message logs from a large-scale messaging system. If your team already has Cassandra expertise or an existing Cassandra system, Keyspaces will feel a lot more natural than learning DynamoDB from scratch.
Timestream: a database purpose-built for time-series data
The last data shape is time series: every record carries a timestamp—server CPU usage, temperature readings streamed every second from an IoT sensor, stock quotes. This kind of data has two defining traits: write volume is usually huge (potentially tens of thousands of records per second), and queries typically need time-window aggregations, like the average over the last hour or the max per minute.
Timestream is a fully managed time-series database built for exactly this pattern: it keeps recent data in a memory tier and automatically moves older data to cheaper storage, and it ships with the statistical functions time-series workloads need built in, so you don't have to implement that aggregation logic in your application layer. Force time-series data into a relational database instead, and query performance typically degrades noticeably as the data grows—which is precisely the problem Timestream exists to solve.
So how do you actually choose?
Looking at these services side by side, the choice really comes down to your data's shape and your query pattern:
| Service | Data Model | Best Fit |
|---|---|---|
| RDS | Relational (managed existing engine) | Apps already built on an existing engine, or needing a specific engine's ecosystem |
| Aurora | Relational (AWS-rewritten engine) | High-performance, highly scalable MySQL/PostgreSQL applications |
| DynamoDB | Key-value/document | Simple query patterns, massive traffic, need for consistent low latency |
| ElastiCache | In-memory (Redis/Memcached) | Cache layer in front of a database, leaderboards, real-time notifications |
| DocumentDB | Document (MongoDB-compatible) | Document-based apps with more complex data, existing MongoDB ecosystem |
| Neptune | Graph | Social graphs, knowledge graphs, recommendation systems, fraud detection |
| Keyspaces | Wide-column (Cassandra-compatible) | Extremely high write volume, low latency across regions, existing Cassandra systems |
| Timestream | Time series | Monitoring metrics, IoT sensor data, and other massive timestamped datasets |
The core logic boils down to one sentence: figure out your data's shape and query pattern first, then decide whether ecosystem compatibility matters, and only then think about scalability and cost. In practice, a real system usually mixes several databases: core transactional data goes in Aurora for consistency, high-traffic user state goes in DynamoDB, a cache layer of ElastiCache sits in front of hot queries, a recommendation engine gets its own Neptune, and monitoring metrics land in Timestream—each one doing its job, rather than forcing everything into a single database.
Wrapping up
RDS, Aurora, DynamoDB, ElastiCache, DocumentDB, Neptune, Keyspaces, and Timestream each map to a different data shape and access pattern. RDS and Aurora handle structured data with strict relationships, DynamoDB and DocumentDB trade that structure for flexibility and scale, ElastiCache uses memory to speed up reads on hot data, Neptune is built specifically for relationships between data, Keyspaces covers the wide-column case for massive write volumes, and Timestream is the dedicated answer for time-series data.