A Guide to AWS Managed Database Services
AWS managed databases has gotten complicated with all the service options, engine choices, and pricing models flying around. As someone who has provisioned and managed databases across every major AWS database service, I learned everything there is to know about choosing and running the right database for your workload. Today, I will share it all with you.
AWS offers over fifteen different database services. That’s not a typo — fifteen. Each one is optimized for specific use cases, and picking the wrong one can cost you in performance, money, or both. I’ve made that mistake before, and it’s not fun to migrate a production database because you chose DynamoDB when you really needed RDS.
Amazon RDS

Probably should have led with this section, honestly. RDS (Relational Database Service) is where most teams start, and for good reason. It supports six database engines: MySQL, PostgreSQL, MariaDB, Oracle, Microsoft SQL Server, and Amazon Aurora. It handles the unglamorous but critical work of patching, backup, recovery, and hardware provisioning so you can focus on your application.
I use RDS for probably 70% of my database needs. Standard web applications, APIs, content management systems — anything that needs ACID transactions and structured data with relationships between tables. RDS just works. You pick your engine, choose your instance size, configure Multi-AZ for high availability, set up automated backups, and you’re done. The operational overhead is minimal compared to running your own database servers.
The thing people underestimate about RDS is the parameter group tuning. The defaults are conservative. For production workloads, I always create custom parameter groups and tune settings like max_connections, innodb_buffer_pool_size (for MySQL), or shared_buffers (for PostgreSQL). Those tweaks alone can improve performance by 30-50% without changing instance size.
Read replicas are another feature I rely on constantly. For read-heavy workloads, spinning up one or two read replicas distributes the query load and keeps your primary instance responsive for writes. Cross-region read replicas also serve as a disaster recovery strategy — if your primary region goes down, you can promote a replica to become the new primary.
Amazon Aurora
Aurora is Amazon’s cloud-native relational database, compatible with MySQL and PostgreSQL but built from the ground up for cloud performance. And honestly? It lives up to the hype. Aurora delivers up to 5x the throughput of standard MySQL and 3x the throughput of PostgreSQL on the same hardware.
That’s what makes Aurora endearing to us database engineers — it gives you the familiar MySQL/PostgreSQL interfaces you already know but with dramatically better performance, automatic storage scaling up to 128TB, and six-way replication across three availability zones by default. The storage layer is where the magic happens — it’s a distributed, fault-tolerant, self-healing storage system that separates compute from storage.
Aurora Serverless v2 is worth special mention. It automatically scales compute capacity up and down based on your workload, measured in ACUs (Aurora Capacity Units). For applications with variable or unpredictable traffic patterns, Serverless v2 can save significant money compared to provisioned instances. I’ve used it for development environments and for applications that spike during business hours but are nearly idle overnight.
Aurora Global Database extends replication across regions with sub-second replication lag, which is essential for applications that need low-latency reads in multiple geographic locations or robust disaster recovery.
For teams migrating from Oracle or SQL Server, Aurora is an attractive option because it offers comparable performance at a fraction of the licensing cost. The Aurora Migration Lab and the Schema Conversion Tool help assess compatibility and automate much of the migration work. I’ve migrated three Oracle databases to Aurora PostgreSQL, and while it required careful testing, the annual cost savings were in the six-figure range.
Aurora’s fast cloning feature deserves mention too. You can create a copy of a multi-terabyte database in seconds using a copy-on-write mechanism. I use this constantly for creating test environments, running data analysis without affecting production, and debugging issues with production data snapshots. The clone is essentially free until you start writing new data to it.
Amazon DynamoDB
DynamoDB is AWS’s fully managed NoSQL database, and it’s a completely different animal from RDS. It’s a key-value and document store designed for single-digit millisecond performance at any scale. If your access patterns are well-defined and you can model your data around a partition key and sort key, DynamoDB is extraordinarily powerful and cost-effective.
I use DynamoDB for session stores, user profiles, IoT data, gaming leaderboards, and any workload where I need consistent, predictable performance regardless of data volume. It scales seamlessly from gigabytes to petabytes without any intervention from you.
The catch — and there’s always a catch — is that DynamoDB requires careful data modeling upfront. You need to know your access patterns before you design your table. Unlike relational databases where you can query any column with reasonable performance, DynamoDB is optimized for specific access patterns defined by your keys and indexes. Retrofitting a DynamoDB table after it’s in production is painful. Trust me on that one.
DynamoDB Streams pairs beautifully with Lambda for event-driven architectures. Every change to your table triggers a stream event that can invoke a Lambda function for real-time processing, notifications, or synchronization to other data stores.
DynamoDB’s on-demand mode vs provisioned capacity mode is a decision that can significantly impact your costs. On-demand mode automatically scales read/write capacity and charges per request, making it ideal for unpredictable workloads or new applications where you don’t know your traffic patterns yet. Provisioned capacity mode lets you reserve throughput at lower per-request costs, which is better for predictable, steady-state workloads. I start most new projects on on-demand mode and switch to provisioned capacity once the access patterns stabilize.
Global tables in DynamoDB provide multi-region, multi-active replication with sub-second replication between regions. For applications that need low-latency access from multiple geographic locations and the ability to handle region-level failures, global tables are invaluable. I’ve deployed global tables for a customer-facing application serving users across North America, Europe, and Asia Pacific, and the consistency and performance have been excellent.
Amazon ElastiCache
ElastiCache provides managed Redis and Memcached instances for in-memory caching. It sits between your application and your database, caching frequently accessed data to reduce latency and database load.
I deploy Redis-based ElastiCache in front of almost every production database. The performance improvement is dramatic — going from 5-10ms database queries to sub-millisecond cache hits makes your application noticeably snappier. For session storage, real-time leaderboards, and frequently accessed reference data, ElastiCache is indispensable.
Redis cluster mode adds automatic sharding across multiple nodes, giving you both the capacity and throughput to handle large caching workloads. I’ve run Redis clusters handling millions of requests per second for real-time applications, and the service is rock-solid.
The choice between Redis and Memcached comes down to your requirements. Redis offers richer data structures (lists, sets, sorted sets, hashes), persistence, replication, and clustering. Memcached is simpler, multi-threaded, and better for pure key-value caching where you don’t need Redis’s advanced features. In practice, I almost always choose Redis because the additional capabilities come at no extra cost and provide flexibility for future requirements.
ElastiCache for Redis now supports JSON data types natively, which simplifies caching complex objects without serialization/deserialization overhead. I’ve seen this reduce application code complexity significantly for APIs that cache structured response data.
Amazon Neptune
Neptune is AWS’s managed graph database, designed for applications where relationships between data points are as important as the data itself. Think social networks, recommendation engines, fraud detection, knowledge graphs, and network topology analysis.
I’ve used Neptune for a recommendation system where we needed to traverse complex user-product-behavior relationships in real time. A relational database would have required dozens of JOINs for the same query, which would have been too slow at our scale. Neptune’s graph traversal approach returned results in milliseconds.
Neptune supports both Apache TinkerPop Gremlin and SPARQL query languages, which gives you flexibility depending on your team’s background and use case.
Amazon Keyspaces (Managed Apache Cassandra)
If you’re running Cassandra workloads, Keyspaces lets you use the same Cassandra Query Language (CQL) and drivers you already know, but without managing the underlying cluster infrastructure. It’s serverless, so you pay for the throughput you consume.
I’ve migrated two Cassandra clusters to Keyspaces, and the operational improvement was significant. No more worrying about node replacements, compaction, or rebalancing. The trade-off is that some advanced Cassandra features aren’t supported, so check the compatibility matrix before committing to a migration.
Amazon DocumentDB (MongoDB Compatible)
DocumentDB provides MongoDB compatibility for teams that use document-oriented data models. It implements the MongoDB API, so your existing MongoDB drivers and tools work with it. Under the hood, it uses Aurora’s storage engine for durability and performance.
The key word is “compatible” not “identical.” DocumentDB implements a subset of the MongoDB API, and certain advanced MongoDB features aren’t supported. I always recommend running your application’s test suite against DocumentDB before migrating to catch any compatibility gaps early.
Amazon Timestream
Timestream is a purpose-built time series database for IoT, operational monitoring, and application metrics. It automatically separates recent data (kept in memory for fast access) from historical data (moved to magnetic storage for cost efficiency), with built-in time series functions for analysis.
For IoT projects with millions of sensor readings or application monitoring with high-frequency metrics, Timestream is dramatically more cost-effective than trying to store time series data in a general-purpose database. The built-in interpolation, smoothing, and approximation functions save significant application-level code.
Amazon QLDB
QLDB (Quantum Ledger Database) provides an immutable, cryptographically verifiable transaction log. If you need a record of every change to your data that cannot be altered or deleted — think financial transactions, supply chain records, or regulatory audit trails — QLDB ensures data integrity at the database level.
Choosing the Right Database
Here’s my practical decision framework when clients ask me which database to use:
- Need ACID transactions and complex queries? Start with RDS or Aurora
- Need single-digit millisecond latency at massive scale with simple access patterns? DynamoDB
- Need to cache frequently accessed data? ElastiCache (Redis)
- Need to model and traverse complex relationships? Neptune
- Need to store time series data? Timestream
- Need an immutable audit log? QLDB
- Already running Cassandra? Consider Keyspaces
- Already running MongoDB? Consider DocumentDB
Don’t overthink it. For most web applications, RDS PostgreSQL or Aurora PostgreSQL covers 80% of use cases. Add DynamoDB for caching session data or high-throughput key-value operations, and you’ve got a database architecture that handles nearly anything.
One common anti-pattern I see is teams choosing a database based on what they already know rather than what fits the workload. If you’re a PostgreSQL expert, it’s tempting to use RDS PostgreSQL for everything, including workloads that would be better served by DynamoDB or ElastiCache. Each database service is optimized for specific access patterns, and using the wrong one creates performance problems that no amount of tuning can fix.
Another consideration is the total cost of ownership. Some services are cheaper per request but more expensive at scale, while others have higher baseline costs but become more economical as usage grows. Model your expected data volume, read/write ratios, and access patterns before committing. AWS’s pricing calculator is your friend here — use it for every database selection decision.
Finally, consider the operational complexity each database adds. Each new database service in your architecture is another service to monitor, another backup to verify, another recovery procedure to test, and another set of credentials to manage. Unless the workload genuinely needs a specialized database, consolidating on fewer database services reduces operational overhead.
Conclusion
AWS’s database portfolio is the most comprehensive in the cloud industry, and that breadth is both a strength and a source of confusion. The key is matching your data characteristics and access patterns to the right service. Start simple, optimize based on real performance data, and don’t migrate to a specialized database until you’ve outgrown the general-purpose options. The managed nature of all these services means you can focus on your application while AWS handles the infrastructure — and that’s exactly how it should be.