Pick the right AWS managed database and understand RDS, Aurora, DynamoDB and ElastiCache!
AWS
Published on
Karl Certa Systems & network administrator5 years in IT, from support to sysadmin, now Ops. Learning cloud, and writing everything down here. Focused on IaC & cloud AWS SAA, Kubernetes next LinkedIn karlcerta.fr GitHub Karl Certa
AWS databases are managed services (relational, NoSQL, cache, analytics): AWS handles hardware, patching, backups and failover, while you keep control of the schema and the queries.
🧭 Choosing the right service
The choice starts from the shape of the data and the kind of queries to serve.
ACID (Atomicity, Consistency, Isolation, Durability): a transaction is applied entirely or not at all, which is what you expect from an orders or billing database.
OLTP (Online Transaction Processing): many small reads/writes, the playground of RDS, Aurora and DynamoDB. OLAP (Online Analytical Processing): few but very heavy queries, the role of Redshift. Running OLAP reports on the production OLTP database slows it down for every user.
Timestream for LiveAnalytics has been closed to new customers since June 20, 2025: AWS points new projects to Timestream for InfluxDB.
🐬 RDS: Relational Database Service
📌 Item
📊 Value / limit
🧩 Supported engines
IBM Db2, MariaDB, Microsoft SQL Server, MySQL, Oracle Database, PostgreSQL
📖 Read Replicas
15 per source instance (default quota, Oracle: 5 recommended to limit lag)
💸 Replication within the same Region
No data transfer charge, billed cross-Region
🧮 Read Replica auto scaling
Not supported: replicas are created and deleted manually
Multi-AZ vs Read Replica
An AZ (Availability Zone) is an availability zone isolated from failures in the other zones of the same Region. RDS offers two Multi-AZ deployments plus Read Replicas, and they don’t address the same need.
📌 Criterion
🔁 Multi-AZ instance
👥 Multi-AZ DB cluster
📖 Read Replica
🎯 Purpose
High availability
High availability and reads
Read scaling, disaster recovery
🔄 Replication
Synchronous
Semi-synchronous (acknowledged by at least 1 reader)
Asynchronous
👀 Readable
No, passive standby
Yes, 2 readers
Yes, read-only
🗺️ Scope
Standby in another AZ
Writer + 2 readers across 3 AZs
Same Region or another Region
⚙️ Failover
Automatic, DNS (Domain Name System) points to the standby, typically 60 to 120 s
Automatic to the most up-to-date reader
Manual: promotion to a standalone instance
🧩 Engines
All (SQL Server through Database Mirroring or Always On)
MySQL and PostgreSQL only
All (Db2 and Oracle also offer non-readable replicas for disaster recovery)
📝 Application side
Same endpoint, connections must be reopened after failover
Reads sent to the readers
Dedicated endpoint to target for reads
RDS backups
📌 Type
⚙️ How it works
📊 Retention
🤖 Automated backups
Volume snapshot during the backup window, transaction logs uploaded every 5 min
0 to 35 days (0 = disabled)
🕐 Default retention
7 days from the console, 1 day from the AWS CLI (Command Line Interface) or the API (Application Programming Interface)
Can be changed afterwards
⏪ PITR (Point-In-Time Recovery)
Restore to any moment within the retention period
Latest restorable time: about 5 min
📸 Manual snapshot
Taken on demand, incremental after the first one
Until deleted, 100 per Region by default
A restore (PITR or snapshot) always creates a new instance: the source instance is not overwritten and the application must be repointed.
Deleting an instance without ticking Retain automated backups erases its automated backups. Manual snapshots are kept.
Changing retention from 0 to a non-zero value (or the reverse) causes an outage of the instance: plan it.
RDS Proxy
RDS Proxy pools connections in front of the database (ideal with Lambda or aggressive autoscaling), can enforce IAM (Identity and Access Management) authentication for clients and is never publicly accessible.
🌟 Aurora
Aurora is the AWS engine compatible with MySQL and PostgreSQL. Its key difference from RDS: compute (instances) and storage (shared cluster volume) are separated.
📌 Criterion
🐬 RDS
🌟 Aurora
💾 Storage
Each instance has its own volume, each replica gets a copy
Cluster (writer), reader (balances across replicas), custom, instance
⏪ Backup retention
0 to 35 days, can be disabled
1 to 35 days, cannot be disabled
🧬 Environment copy
Snapshot restore
Copy-on-write cloning: only modified data is copied
Serverless and Global Database
📌 Feature
⚙️ How it works
📊 Limits
☁️ Aurora Serverless v2
Capacity adjusted continuously in 0.5 ACU steps (Aurora Capacity Unit, about 2 GiB of memory with processor and networking)
0 to 256 ACUs depending on version, 0 = automatic pause
🌍 Global Database
1 primary Region for writes, read-only secondary Regions, replication through the storage layer
Up to 10 secondary Regions, 16 replicas per secondary cluster, typical lag under a second
🔀 Switchover / failover
Switchover: planned Region change with no data loss. Failover: recovery from a Regional outage
Global writer endpoint that follows the primary Region
✍️ Write forwarding
Secondary clusters forward writes to the primary
Option to enable
Aurora Serverless v1 is a deprecated product, with an architecture different from the v2 described here.
🔑 DynamoDB
DynamoDB is a fully managed NoSQL key-value and document database: no instance to size, you create tables and pick a capacity mode.
📌 Item
📊 Value / limit
📦 Max item size
400 KB, attribute names included
🗂️ Secondary indexes
5 LSI (Local Secondary Index) and 20 GSI (Global Secondary Index) per table, default quotas
📖 1 RCU (Read Capacity Unit)
1 strongly consistent read/s or 2 eventually consistent reads/s, item up to 4 KB
✏️ 1 WCU (Write Capacity Unit)
1 write/s, item up to 1 KB
💳 Transactions
Double cost: 2 RCUs or 2 WCUs per operation
📄 Query / Scan
1 MB of results max per call, pagination beyond that
Units are rounded up: a 3 KB item read with strong consistency uses 1 RCU, a 5 KB item uses 2. Reads are eventually consistent by default, which halves their cost.
Capacity modes
📌 Criterion
⚡ On-demand
📐 Provisioned
💳 Billing
Per request
Per hour, on provisioned capacity even if unused
📈 Scaling
Automatic, nothing to plan
Declared RCU/WCU, optional auto scaling (recommended target: 70%)
🎯 Use
Default and recommended mode, unpredictable traffic
Steady, predictable load, controlled cost
🔄 Switching modes
To provisioned: any time
To on-demand: 4 times max per rolling 24 h
Key features
📌 Feature
⚙️ Role
📊 Remember
⚡ DAX (DynamoDB Accelerator)
In-memory cache compatible with the DynamoDB API
Microsecond latency, default TTL (Time To Live) 5 min, 1 primary node + 0 to 10 replicas, strongly consistent reads never cached
📜 Streams
Log of item changes, or CDC (Change Data Capture), consumable by Lambda
24 h retention, each change appears once and in order for a given item
🌍 Global Tables
Multi-Region replication, every replica accepts reads and writes
MREC (Multi-Region Eventual Consistency, default): asynchronous, usually under a second, “last writer wins”. MRSC (Multi-Region Strong Consistency): synchronous, exactly 3 Regions
⏳ TTL
Deletion of expired items, Number attribute in epoch seconds
Usually deleted within a few days, without consuming WCUs
⏪ PITR
Continuous backup to enable, per-second restore
1 to 35 day window, restore into a new table
💾 On-demand backup
Full backup triggered manually
Kept until explicitly deleted
An expired item remains visible to reads until TTL deletes it: filter on the TTL attribute in Query and Scan.
In MREC mode, Streams are enabled automatically on replicas to handle replication. MRSC offers an RPO (Recovery Point Objective, maximum data loss) of zero, but supports neither TTL nor transactions.
⚡ ElastiCache
📌 Criterion
🟥 Valkey / Redis OSS (Open Source Software)
🟦 Memcached
🧩 Data types
Rich: lists, sets, sorted sets, hashes, pub/sub
Simple key-value
🔁 Replication, high availability
Yes, with automatic failover
No
💾 Backup and restore
Yes
Serverless mode only
🧱 Partitioning
Yes with cluster mode enabled
Yes
🎯 Typical use case
Cache, sessions, leaderboards (sorted sets)
Simple cache on large multi-core nodes
Caching strategies
📌 Strategy
⚙️ How it works
⚠️ Limitation
💤 Lazy loading (cache-aside)
The app reads the cache, on a miss it reads the database then writes the result to the cache
Potentially stale data, 3 round trips on every miss
✍️ Write-through
Every database write also updates the cache
Cache filled with data never read, empty on a new node
⏳ Adding a TTL
Expiration set on each key, can be combined with both
Limits staleness and clutter
Unlike DAX, ElastiCache is not transparent: caching logic is coded in the application.