RDS (with Aurora and ElastiCache) — DVA-C02 Mastery Guide
- Sources: course chapter 03 (RDS, Aurora and ElastiCache), used as the syllabus only; every sentence here is original. Facts come from the AWS documentation pages listed in Changed vs older material.
- Written 2026-10-12; values checked against AWS docs on 2026-10-12.
⚠️ Changed: <current>. Older material may say <old>.marks a value or behaviour that differs from the course or from older practice tests: learn the current value.⚠️ unverifiedmarks a claim not confirmed in current AWS documentation: never rely on it. Dated items ("since 2026-02-18") are recent and often missing from practice tests.- Tier 3 (supporting), bank target 25 questions. Domains: Development with AWS Services (primary), Troubleshooting and Optimization. Encryption and IAM database authentication are security topics the exam asks about in database scenarios; this module's bank files them under its two domains.
- How to use it:
/explain <topic>teaches from these sections (concept → exam facts → developer angle → traps → 3 check questions);/quiz rdsasks bank questions whosesource_notelinks point at the## N.headings below;/drill rdsfires short recall prompts fromnotes/rds-cheat-sheet.md. Loop: read a section → answer its two practice questions before opening the answers →/explainthe gaps →/quiz rds→/drill rds.
How RDS (with Aurora and ElastiCache) appears on DVA-C02
DVA-C02 treats relational databases and caches as data stores your code depends on, not as servers to administer. Expect:
- Choosing a data store or feature under a constraint: read replica vs Multi-AZ vs Aurora replica; provisioned capacity vs Aurora Serverless v2; ElastiCache vs MemoryDB (DynamoDB and DAX belong to the dynamodb module).
- Connecting code safely and efficiently: endpoints, connection pooling with RDS Proxy (above all from Lambda), IAM database authentication tokens, Secrets Manager credentials, TLS.
- Caching logic you write: lazy loading vs write-through, TTLs, evictions, session stores, leaderboards.
- Troubleshooting:
Too many connections, replica lag and stale reads, reconnecting after failover (DNS caching), pinned proxy sessions, cache misses and evictions,storage-full, restores that come back on a new endpoint.
Typical question shapes: a scenario with one deciding constraint (LEAST operational overhead, fewest code changes, MOST secure, MOST cost-effective, lowest latency); a metric or error message to diagnose; "Which TWO…" with five options; the exact CLI option, API parameter or IAM action that does the job.
Domain map: Development with AWS Services → §1, §2, §4, §5, §6, §9, §10 · Troubleshooting and Optimization → §1 (storage, connections), §2 (lag), §3 (failover), §6 (pinning), §8 (restores), §10 (hit rate, evictions) · exam-wide security angles → §6 (IAM at the proxy), §7.
Owned by other modules (one-line pointers): KMS key types, key policies and envelope encryption → notes/security-encryption-guide.md §1–§6 · Secrets Manager rotation and RDS-managed master passwords → notes/security-encryption-guide.md §10–§11 · DAX vs ElastiCache for DynamoDB → notes/dynamodb-guide.md §10 · DynamoDB as a session store → notes/dynamodb-guide.md §14 · Lambda VPC attachment and reserved concurrency → notes/lambda-guide.md §10 and §5 · security groups and connection timeouts → notes/ec2-mastery-guide.md §4 · subnets, NAT gateways and VPC endpoints → notes/vpc-guide.md · CloudWatch alarms, Logs Insights and EventBridge rules → notes/monitoring-guide.md · DeletionPolicy: Snapshot for databases → notes/cloudformation-guide.md §9 · dynamic references for database passwords → notes/cloudformation-guide.md §14 · RDS coupled to an Elastic Beanstalk environment → notes/beanstalk-guide.md §11 · SigV4 presigned requests → notes/cli-sdk-policies-guide.md §10 · retries with backoff → notes/cli-sdk-policies-guide.md §9.
Out of scope: database administration depth (query tuning, engine internals, host access) and network design.
| # | Topic | Why it is on the exam |
|---|---|---|
| 1 | RDS fundamentals and storage auto scaling | What AWS manages vs what your code owns; endpoints, parameter groups and connection limits; storage that grows by itself |
| 2 | Read replicas | Offloading reads, stale reads and lag, cross-Region copies, promotion |
| 3 | Multi AZ deployments and failover | Automatic failover vs read scaling; reconnect logic; Multi-AZ DB clusters; low-downtime blue/green changes |
| 4 | Aurora storage endpoints and replicas | Writer, reader and custom endpoints; failover tiers; replica auto scaling; Global Database |
| 5 | Aurora Serverless and the Data API | Capacity that follows the load, down to zero; SQL over HTTPS without drivers |
| 6 | RDS Proxy | Connection storms from Lambda, faster failover, IAM at the proxy, pinning |
| 7 | Encryption and IAM database authentication | KMS at rest, TLS in transit, password-free logins with rds-db:connect |
| 8 | Backups snapshots and restores | PITR, copying and sharing snapshots, Backtrack and cloning; every restore is a new endpoint |
| 9 | ElastiCache engines and MemoryDB | Valkey/Redis OSS vs Memcached, serverless vs node-based, authentication, durability, MemoryDB |
| 10 | Caching strategies TTL and session stores | Lazy loading vs write-through, TTLs and evictions, sessions and leaderboards |
1. RDS fundamentals and storage auto scaling
Concept
- Amazon RDS runs a relational engine for you. You pick the engine, the DB instance class, the storage and the network placement; AWS provisions the host, patches the OS and engine in your maintenance window, takes backups, detects failures and runs failover and replication. Your code still owns the schema, the queries, the indexes and how it opens and reuses connections.
- Engines: IBM Db2, MariaDB, Microsoft SQL Server, MySQL, Oracle Database and PostgreSQL. Amazon Aurora (MySQL- and PostgreSQL-compatible) is driven through the same RDS API and console but has its own architecture (§4).
- You never get a shell on the host. Applications that need OS-level or privileged database access use RDS Custom (Oracle and SQL Server only) or a self-managed database on EC2.
- What a developer touches: the endpoint (DNS name + port, never an IP), the DB subnet group (subnets the instance may use), VPC security groups (which clients may connect), the DB parameter group (engine settings such as
max_connectionsor TLS enforcement), the option group (engine add-ons) and the master user. - Storage is EBS-based: gp3 (recommended general purpose), gp2, io2 Block Express and io1 (Provisioned IOPS); magnetic storage is deprecated. Storage autoscaling raises the allocated storage automatically when free space runs low, up to a ceiling you choose.
Exam facts
- Storage autoscaling is on when
MaxAllocatedStorage(--max-allocated-storage) is above the allocated size; setting it equal to the allocated size turns it off. Changing it applies immediately, needs no reboot and ignores Apply immediately. - RDS grows the storage when all of these hold: free space ≤ 10 % of allocated storage; the low-space condition lasts ≥ 5 minutes; the previous storage modification has finished optimizing and fewer than four storage modifications happened in the past 24 hours. ⚠️ Changed: the gate is "previous optimization finished and fewer than 4 storage modifications in 24 hours". Older material may say "a 6-hour wait after the last storage modification".
- Each increase adds the largest of 10 GiB, 10 % of the current allocation, or the growth predicted for the next 7 hours from the past hour of
FreeStorageSpace. - The ceiling must be at least 10 % above the current allocation (otherwise
Invalid max storage size); AWS suggests ≥ 26 % to avoid the "approaching maximum" eventRDS-EVENT-0225; the default ceiling is 1,000 GiB. Autoscaling never grows past the ceiling. - Storage never shrinks — not through autoscaling, not through
modify-db-instance. To get smaller storage: a blue/green deployment with less storage (§3; not for an instance whose master password RDS manages in Secrets Manager, likeorders-dbbelow, untilmodify-db-instance --no-manage-master-user-password --master-user-password …turns that off), or a new instance plus data migration. - Autoscaling is not a safety net for one huge load: with optimization waits and the 4-per-24-hours cap, an instance can stay
storage-fullfor hours. Size storage before bulk loads. - Not available with magnetic storage, a few old db.m3 classes, the additional storage volumes of Oracle/SQL Server, RDS Custom or Multi-AZ DB clusters (scale those manually). Aurora has no
MaxAllocatedStorage: its cluster volume grows by itself (§4). Autoscaling operations aren't logged in CloudTrail. - Size limits: 64 TiB per instance for Db2, MariaDB, MySQL and PostgreSQL; RDS for Oracle and SQL Server reach 256 TiB with up to three additional storage volumes. Manual increases must be ≥ 10 %.
max_connectionsdefaults scale with memory (MySQL{DBInstanceClassMemory/12582880}, PostgreSQLLEAST({DBInstanceClassMemory/9531392},5000)); a MySQL db.t3.micro allows about 60. Exhausting it gives MySQL error 1040Too many connectionsor PostgreSQLFATAL: sorry, too many clients already→ pool connections, use RDS Proxy (§6) or a larger class.- Default engine ports: MySQL and MariaDB 3306, PostgreSQL 5432, Oracle 1521, SQL Server 1433, Db2 50000 (
--portaccepts 1150–65535). PubliclyAccessibledecides whether the endpoint resolves to a public IP. Production databases stay private in a DB subnet group whose security group admits only the application's security group (connectivity troubleshooting:notes/ec2-mastery-guide.md§4).- Too many RDS API calls return
ThrottlingException(Rate exceeded): retry with backoff (notes/cli-sdk-policies-guide.md§9). - A stopped instance starts again automatically after 7 consecutive days; storage and backups are still billed; an instance that has, or is, a read replica can't be stopped.
- Default quota: 40 DB instances per Region (adjustable; shared with Aurora, Neptune and DocumentDB instances).
- Observability (details in
notes/monitoring-guide.md): RDS sends metrics to CloudWatch every minute at no charge (CPUUtilization,FreeStorageSpace,DatabaseConnections,FreeableMemory,ReadLatency/WriteLatency); Enhanced Monitoring adds OS metrics atMonitoringInterval1, 5, 10, 15, 30 or 60 s (0 = off; needs a monitoring role); engine logs can be exported to CloudWatch Logs. ⚠️ Changed: database-load analysis now lives in CloudWatch Database Insights; the Performance Insights console experience reached end of life on 2025-11-30 (the Performance Insights API remains). Older material may say "open the Performance Insights dashboard".
Developer angle
Create a private PostgreSQL instance whose storage can grow from 100 GiB to 500 GiB:
aws rds create-db-instance \
--db-instance-identifier orders-db \
--engine postgres \
--db-instance-class db.m7g.large \
--storage-type gp3 \
--allocated-storage 100 \
--max-allocated-storage 500 \
--master-username orders_admin \
--manage-master-user-password \
--db-subnet-group-name orders-private \
--vpc-security-group-ids sg-0db1234567890abcd \
--no-publicly-accessible \
--backup-retention-period 7 \
--storage-encrypted
# Connection details for the application: always the DNS name, never an IP
aws rds describe-db-instances --db-instance-identifier orders-db \
--query 'DBInstances[0].Endpoint.[Address,Port]' --output text
# Can this instance autoscale storage? Look for SupportsStorageAutoscaling
aws rds describe-valid-db-instance-modifications --db-instance-identifier orders-db
# Raise the ceiling later (immediate, no downtime)
aws rds modify-db-instance --db-instance-identifier orders-db --max-allocated-storage 800
--manage-master-user-password keeps the master password in Secrets Manager (rotation: notes/security-encryption-guide.md §11).
| Symptom | Likely cause | Developer fix |
|---|---|---|
| Connection attempt times out | Security group or routing, or a private endpoint reached from outside the VPC | Allow the app's security group on the DB port; connect from inside the VPC |
Too many connections / too many clients already |
max_connections exhausted by many short-lived clients |
RDS Proxy or a connection pool; a larger class only if memory is the limit |
Status storage-full, writes fail |
Storage ran out (autoscaling off, capped or rate-limited) | Raise allocated storage or MaxAllocatedStorage; pre-size before bulk loads |
Invalid max storage size |
Ceiling less than 10 % above allocated storage | Choose a ceiling at least 10 % (better 26 %) higher |
Traps
- Trap: "SSH into the RDS host to tune the OS." → Reality: not possible; only RDS Custom (Oracle, SQL Server) gives host access.
- Trap: "Storage autoscaling shrinks the volume after a purge." → Reality: RDS storage only grows.
- Trap: "Autoscaling makes a large one-time import safe." → Reality: optimization waits and the 4-per-24-hours cap can leave it
storage-full; pre-size. - Trap: "Turning on storage autoscaling waits for the maintenance window." → Reality: it applies immediately without downtime.
- Trap: "Set
MaxAllocatedStorageon an Aurora cluster." → Reality: Aurora's cluster volume grows automatically. - Trap: "A stopped dev database stays stopped until someone starts it." → Reality: RDS starts it after 7 days.
- Trap: "Hard-code the instance IP for speed." → Reality: always use the endpoint; IPs change on failover and host replacement.
Practice questions
-
A startup runs its mobile backend on Amazon RDS for MySQL. User growth is unpredictable, and last night the instance entered the
storage-fullstate and rejected writes. The team wants storage to grow automatically from now on, without downtime and with the LEAST operational overhead. What should a developer do?- A. Create a CloudWatch alarm on
FreeStorageSpacethat invokes a Lambda function to callmodify-db-instancewith a larger--allocated-storage. - B. Modify the instance with a
--max-allocated-storagevalue higher than its allocated storage. - C. Convert the instance to a Multi-AZ deployment so that the standby adds storage capacity.
- D. Move the data to an Amazon ElastiCache cluster and keep only reference data in RDS.
- A. Create a CloudWatch alarm on
-
A developer turned on storage autoscaling for an Amazon RDS for PostgreSQL instance with 1,000 GiB allocated and a maximum storage threshold of 1,100 GiB. During a large weekend import, the instance still ran out of space. Which TWO statements explain the behaviour? (Select TWO.)
- A. The threshold left room for only one increase, and autoscaling never grows storage beyond the maximum storage threshold.
- B. Storage autoscaling works only with gp2 volumes, not gp3 volumes.
- C. Autoscaling waits for the previous modification to finish optimizing and allows fewer than four storage modifications in 24 hours, so a fast load can outrun it.
- D. Storage autoscaling requires a reboot after each increase, which was postponed to the maintenance window.
- E. Storage autoscaling is available only for Aurora clusters.
Answers
- B. A
MaxAllocatedStoragevalue above the allocated size turns on storage autoscaling: managed, immediate, no downtime. A works but is custom automation (more overhead); C adds a standby for availability, not capacity; D needs application rewrites. - A, C. One increase to 1,100 GiB used up the threshold, and autoscaling is rate-limited by optimization and the four-per-24-hours rule. B is wrong (gp3 is supported; magnetic isn't); D is wrong (no reboot is involved); E is wrong (Aurora grows its own volume; storage autoscaling is an RDS instance feature).
2. Read replicas
Concept
- A read replica is a separate DB instance that the engine's asynchronous replication keeps up to date with the source. Read-only work (reports, analytics, read-heavy API calls) goes to the replica's own endpoint; the source keeps all writes.
- Asynchronous means lag: right after a write, a replica can still return the old row. Code that must read its own writes reads from the source.
- Creating a replica: RDS snapshots the source (a Single-AZ source pauses I/O for about a second; a Multi-AZ source is snapshotted from its standby, so no pause), builds the replica from that snapshot and then streams changes. Replicas can live in the same AZ, another AZ or another Region.
- Promotion turns a replica into an independent, writable instance: replication stops for good and the instance reboots. Uses: disaster recovery, splitting a database (sharding), or running slow DDL on a MySQL/MariaDB replica before switching to it.
- A replica isn't high availability by itself: nothing fails over to it automatically, and each replica has a different endpoint, so the application decides where reads go.
Exam facts
- Up to 15 read replicas per source (quota Read replicas per primary, adjustable for RDS) for MySQL, MariaDB, PostgreSQL, Oracle and SQL Server; RDS for Db2 allows up to 3. AWS recommends ≤ 5 for Oracle, and SQL Server replicas lag more beyond 5.
- The source must have automated backups turned on (backup retention ≠ 0) — also a replica that is itself the source of another replica; retention can't be set to 0 while replicas exist.
- RDS can't create a read replica of a source whose master password it manages in Secrets Manager (
--manage-master-user-password, likeorders-dbin §1), except on RDS for SQL Server and Db2. - Writable replicas: only MySQL and MariaDB (set
read_only = 0in the replica's parameter group). PostgreSQL, Oracle, SQL Server and Db2 replicas stay read-only until promoted. - Replica of a replica: MySQL, MariaDB and some PostgreSQL versions; not Db2, Oracle or SQL Server. Circular replication isn't supported.
- A replica can be created as a Multi-AZ DB instance (its own synchronous standby), whatever the source's setup — except on RDS for SQL Server, which supports no Multi-AZ replicas.
- Costs: replication data transfer inside one Region is free; cross-Region replication pays data transfer out of the source Region (initial snapshot copy plus every change). For MySQL/MariaDB, chain extra remote replicas from the first remote replica to pay the cross-Region transfer only once.
- Cross-Region: run the command in the destination Region with the source ARN; an encrypted source needs
--kms-key-idfrom the destination Region; RDS can't guarantee more than five cross-Region replicas per source; the replica gets the default security group and usually the default parameter group. The caller needsrds:CreateDBInstanceReadReplicaon the source and replica ARNs, and anaws:RequestedRegioncondition must list both Regions. - Encryption must match the source: no encrypted replica of an unencrypted source and no unencrypted replica of an encrypted one (§7).
- Deleting a source promotes its same-Region replicas; a cross-Region PostgreSQL replica instead shows replication status
terminatedand must be promoted or deleted by hand. - RDS never adds or removes replicas for you (Aurora Auto Scaling does that for Aurora, §4), and RDS instance replicas have no shared reader endpoint (Aurora clusters and Multi-AZ DB clusters do).
ReplicaLag(CloudWatch, seconds) shows how far a replica trails. Before a planned promotion, stop writes on the source and wait forReplicaLag= 0.- A promoted replica keeps its parameter and option groups and can get its own replicas and PITR, but it can never become a replica again.
Developer angle
# Same-Region replica for reporting traffic (inventory-db keeps its own password, not an RDS-managed secret)
aws rds create-db-instance-read-replica \
--db-instance-identifier inventory-replica-1 \
--source-db-instance-identifier inventory-db \
--db-instance-class db.r7g.large
# Encrypted cross-Region replica, created from the destination Region
aws rds create-db-instance-read-replica --region eu-central-1 \
--db-instance-identifier inventory-replica-fra \
--source-db-instance-identifier arn:aws:rds:eu-west-1:111122223333:db:inventory-db \
--kms-key-id alias/inventory-rds-fra
# Alarm when the replica falls more than 30 s behind for 5 minutes
aws cloudwatch put-metric-alarm --alarm-name inventory-replica-lag \
--namespace AWS/RDS --metric-name ReplicaLag \
--dimensions Name=DBInstanceIdentifier,Value=inventory-replica-1 \
--statistic Maximum --period 60 --evaluation-periods 5 \
--threshold 30 --comparison-operator GreaterThanThreshold \
--alarm-actions arn:aws:sns:eu-west-1:111122223333:db-alerts
# Disaster recovery: turn the remote replica into a standalone, writable instance
aws rds promote-read-replica --db-instance-identifier inventory-replica-fra \
--backup-retention-period 7
Route each query to the right endpoint (real applications keep one pool per endpoint):
import json
import os
import boto3
import psycopg2
_secret = json.loads(boto3.client("secretsmanager").get_secret_value(
SecretId=os.environ["DB_SECRET_ARN"])["SecretString"])
def connect(read_only: bool):
# Reports tolerate a few seconds of lag; "show the stock level I just updated" does not.
host = os.environ["DB_REPLICA_HOST"] if read_only else os.environ["DB_PRIMARY_HOST"]
return psycopg2.connect(host=host, port=5432, dbname="inventory",
user=_secret["username"], password=_secret["password"],
sslmode="verify-full",
sslrootcert="/opt/certs/global-bundle.pem")
Traps
- Trap: "If the primary fails, RDS fails over to the read replica." → Reality: that is Multi-AZ (§3); promoting a replica is a manual call.
- Trap: "All replicas share one reader endpoint." → Reality: each RDS replica has its own endpoint; reader endpoints belong to Aurora and Multi-AZ DB clusters.
- Trap: "Read your own write from the replica." → Reality: asynchronous lag can return stale rows; read from the source.
- Trap: "Turn off automated backups on the primary to save money." → Reality: replicas then can't be created or kept.
- Trap: "Same-Region replicas pay cross-AZ data transfer." → Reality: in-Region replication is free; cross-Region is charged.
- Trap: "Encrypt only the replica and leave the primary unencrypted." → Reality: the encryption state must match (§7).
- Trap: "Promote now and re-attach the replica later." → Reality: promotion is permanent.
Practice questions
-
A retailer's Amazon RDS for PostgreSQL instance serves an order-processing application. A new reporting tool runs long
SELECTqueries that slow order processing down. The reports can tolerate data that is a few seconds old. Which solution meets these requirements MOST cost-effectively?- A. Convert the instance to a Multi-AZ DB instance deployment and point the reporting tool at the standby.
- B. Scale the instance up to the next larger instance class.
- C. Create a read replica and point the reporting tool at the replica's endpoint.
- D. Add an Amazon ElastiCache cluster and rewrite the reporting tool to cache query results.
-
Users of a web application on Amazon RDS for MySQL sometimes don't see a profile change right after saving it, because reads go to a read replica. The team also wants an alert when the replica falls more than 30 seconds behind. Which TWO actions meet these requirements? (Select TWO.)
- A. Enable Multi-AZ on the read replica to make replication from the source synchronous.
- B. Send reads that immediately follow a write by the same user to the source DB instance endpoint.
- C. Increase the backup retention period of the source DB instance.
- D. Create a CloudWatch alarm on the replica's
ReplicaLagmetric with a 30-second threshold. - E. Promote the read replica so that it receives the writes directly.
Answers
- C. A replica takes the read load off the source for the price of one more instance, and the reports accept slight lag. A fails because a Multi-AZ DB instance standby can't serve reads; B costs more and still mixes both workloads; D needs code changes and doesn't remove the long queries.
- B, D. Read-after-write traffic must hit the source because replication is asynchronous, and
ReplicaLag(seconds) is the metric to alarm on. A gives the replica its own standby but leaves source-to-replica replication asynchronous; C has nothing to do with lag; E breaks replication and leaves two diverging databases.
3. Multi AZ deployments and failover
Concept
- Multi-AZ is about availability: if the primary's host, storage, network or whole AZ fails, RDS fails over automatically and the endpoint name stays the same.
- Multi-AZ DB instance deployment: one primary plus one synchronous standby in another AZ. The standby can't serve reads. On failover RDS points the endpoint's DNS record at the standby; failover typically takes 60–120 seconds.
- Multi-AZ DB cluster deployment (RDS for MySQL and PostgreSQL): one writer plus two readable reader instances in three AZs, semisynchronous replication (a commit needs at least one reader's acknowledgement), a cluster (writer) endpoint, a reader endpoint and instance endpoints. Failover typically finishes in under 35 seconds, and write latency is usually lower than with a Multi-AZ DB instance.
- After any failover, existing connections break: applications must reconnect with retries and must not cache the old IP (keep the JVM DNS TTL at 60 seconds or less).
- Multi-AZ and read replicas combine: a Multi-AZ primary for availability plus replicas (themselves optionally Multi-AZ) for read scale. Neither survives a Region outage — that needs cross-Region replicas or Aurora Global Database.
- Blue/green deployments handle planned changes with little downtime: RDS builds a synchronized green copy (new engine version, parameter group, instance class or storage), you test it, then switch over. Switchover typically takes under a minute with no data loss, and the endpoints move to green, so connection strings don't change.
Exam facts
- Failover triggers: AZ, host or storage failure, lost network connectivity, offline OS patching, some instance modifications (for example a class change), an unresponsive primary and reboot with failover.
- Test it:
aws rds reboot-db-instance --force-failoverfor a Multi-AZ DB instance;aws rds failover-db-clusterfor a Multi-AZ DB cluster (and for Aurora). - Know when it happened: RDS event notifications (category
failover) to SNS, or the same events through EventBridge. - Single-AZ → Multi-AZ (
modify-db-instance --multi-az): RDS snapshots the primary's EBS volumes, builds the standby's volumes from the snapshot (they hydrate in the background) and starts synchronous block-level replication. No downtime, but write latency can rise; for busy production instances AWS suggests converting a read replica to Multi-AZ and promoting it instead. EventRDS-EVENT-0025marks completion. - Synchronous replication adds write and commit latency compared with Single-AZ; Provisioned IOPS storage is recommended for production Multi-AZ.
- Snapshots of a Multi-AZ DB instance are taken from the standby, so the primary's I/O isn't suspended.
- Data transferred between AZs for Multi-AZ replication is free.
- Multi-AZ DB clusters: backup retention 1–35 days; only certain instance classes (local NVMe classes such as db.m6gd or db.r6gd); their snapshots can't be shared or copied;
ReplicaLagreports reader lag. - ⚠️ Changed: Multi-AZ can also scale reads when you choose a Multi-AZ DB cluster (two readable standbys behind a reader endpoint). Older material may say "Multi-AZ standbys never serve reads; Multi-AZ is not for read scaling" (still true for a Multi-AZ DB instance).
- Blue/green deployments: RDS for MariaDB, MySQL and PostgreSQL (and Aurora); not for Multi-AZ DB clusters, cascading or cross-Region replicas, instances whose master password is managed in Secrets Manager, or through CloudFormation. Keep client DNS caching at or below the 5-second RDS record TTL so writes follow the switchover. Green is read-only by default; after switchover the old blue instances get an
-old1suffix and stay running; PITR history doesn't carry over to the new production instance; IAM DB auth policies must list the green resource ID too (resource IDs differ). - Aurora handles availability differently: storage always spans three AZs and Aurora Replicas are the failover targets (§4).
Developer angle
# Add a synchronous standby (no downtime; watch write latency)
aws rds modify-db-instance --db-instance-identifier orders-db --multi-az --apply-immediately
# Rehearse a failover and get notified
aws rds reboot-db-instance --db-instance-identifier orders-db --force-failover
aws rds create-event-subscription --subscription-name orders-failover \
--sns-topic-arn arn:aws:sns:eu-west-1:111122223333:db-alerts \
--source-type db-instance --source-ids orders-db --event-categories failover
# Multi-AZ DB cluster: manual failover to a reader
aws rds failover-db-cluster --db-cluster-identifier orders-maz
# Low-downtime major upgrade with blue/green (billing-db keeps its own password, not an RDS-managed secret)
aws rds create-blue-green-deployment --blue-green-deployment-name billing-pg17 \
--source arn:aws:rds:eu-west-1:111122223333:db:billing-db \
--target-engine-version 17.4 --target-db-parameter-group-name billing-pg17
aws rds switchover-blue-green-deployment \
--blue-green-deployment-identifier bgd-0123456789abcdef --switchover-timeout 300
Reconnect after a failover instead of crashing:
import time
import psycopg2
def connect_with_retry(dsn: str, attempts: int = 6):
delay = 1.0
for attempt in range(1, attempts + 1):
try:
return psycopg2.connect(dsn, connect_timeout=5)
except psycopg2.OperationalError:
if attempt == attempts:
raise
time.sleep(delay) # back off while the endpoint's DNS moves to the new primary
delay = min(delay * 2, 20)
In Java, set networkaddress.cache.ttl=60 (or lower) in java.security, or call java.security.Security.setProperty("networkaddress.cache.ttl", "60") before the first connection. The switchover timeout of a blue/green deployment is 30–3,600 s (default 300).
Traps
- Trap: "Send reads to the Multi-AZ standby." → Reality: a Multi-AZ DB instance standby can't be read; use a replica or a Multi-AZ DB cluster's reader endpoint.
- Trap: "After failover, change the connection string to the standby." → Reality: the endpoint name stays the same; just reconnect.
- Trap: "Failover is instant, so no retry logic is needed." → Reality: 60–120 s for a Multi-AZ DB instance (< 35 s for a Multi-AZ DB cluster); code must retry and refresh DNS.
- Trap: "Multi-AZ survives a Region outage." → Reality: it spans AZs of one Region only.
- Trap: "Converting to Multi-AZ means downtime." → Reality: it doesn't, though write latency can rise.
- Trap: "The read replica is the Multi-AZ standby." → Reality: replicas are asynchronous and never take over automatically.
Practice questions
-
A Java application on Amazon EC2 connects to an Amazon RDS for MySQL Multi-AZ DB instance through its endpoint. During a failover test, RDS reported that failover completed in about two minutes, but the application kept failing to connect for more than 30 minutes until it was restarted. What should a developer change?
- A. Point the application at the standby instance's endpoint after each failover.
- B. Turn on storage autoscaling for the DB instance.
- C. Add a read replica in the standby's Availability Zone.
- D. Set the JVM DNS cache TTL (
networkaddress.cache.ttl) to 60 seconds or less.
-
A company needs an Amazon RDS for PostgreSQL database that fails over automatically in less than a minute and can also run read-only queries on its standby instances. The team doesn't want to manage replicas by hand. Which TWO actions meet these requirements? (Select TWO.)
- A. Create a Multi-AZ DB instance deployment and send reads to the standby.
- B. Create a cross-Region read replica and promote it when the primary fails.
- C. Create the database as a Multi-AZ DB cluster deployment.
- D. Reboot the primary with
--force-failoverevery night to keep the standby warm. - E. Send read-only queries to the cluster's reader endpoint.
Answers
- D. The endpoint name never changes, but a JVM that caches DNS indefinitely keeps dialling the failed host's old IP. A is wrong because there is no separate standby endpoint to use; B and C don't affect name resolution.
- C, E. A Multi-AZ DB cluster has two readable standbys, typically fails over in under 35 seconds and exposes a reader endpoint. A fails because a Multi-AZ DB instance standby can't serve reads; B is a manual, slower disaster-recovery path; D only causes outages.
4. Aurora storage endpoints and replicas
Concept
- Aurora separates compute from storage. Every DB instance in a cluster reads one shared cluster volume that keeps six copies of the data across three AZs, whatever the number of instances.
- A cluster has one writer (primary) and up to 15 Aurora Replicas (readers). Replicas read the same volume instead of replaying their own copy, so lag stays small; they are also the failover targets.
- Endpoints route connections so code never hard-codes instance hosts:
| Endpoint | DNS pattern | Use |
|---|---|---|
| Cluster (writer) | name.cluster-xxxx.<region>.rds.amazonaws.com |
Reads and writes; follows the current writer after failover |
| Reader | name.cluster-ro-xxxx.<region>.rds.amazonaws.com |
Read-only sessions, balanced per connection across replicas |
| Custom | name.cluster-custom-xxxx.<region>.rds.amazonaws.com |
A chosen subset of instances (for example large instances for reports) |
| Instance | one per instance | Diagnostics on a single instance; doesn't follow failover |
| Global Database writer | one per global cluster | Always points at the primary Region's writer, even after a cross-Region switchover |
- The cluster volume grows as data grows and shrinks (frees billed space) when you drop data. Two storage configurations: Aurora Standard (pay per I/O request) and Aurora I/O-Optimized (no I/O charges; the better choice when I/O is ≥ 25 % of the Aurora bill).
- Aurora Auto Scaling adds and removes replicas through Application Auto Scaling; Aurora Global Database copies a cluster into other Regions for local reads and Region-level recovery.
Exam facts
- Quorum (AWS Database Blog): six copies, writes need 4 and reads need 3; losing a whole AZ keeps write availability, and an AZ plus one more copy can be lost without losing data.
- ⚠️ Changed: replica lag is usually much less than 100 milliseconds. Older material may say "under 10 ms".
- ⚠️ Changed: with at least one replica, service is typically restored in less than 60 seconds and often in less than 30; without replicas Aurora recreates the writer in the same AZ, typically in under 10 minutes. Older material may say "failover is instantaneous" or "always under 30 seconds".
- Failover target: the best promotion tier wins (0 = highest priority … 15 = lowest); on a tie the largest instance wins, then any. Changing a tier doesn't cause a failover. Replicas added by Aurora Auto Scaling get tier 15.
- The reader endpoint balances connections, not queries: open new connections to spread work. With no replicas it reaches the writer (writes succeed through it), and right after a failover it can briefly point at the new writer. It can't be created, deleted or modified.
- Custom endpoints: up to 5 per cluster (adjustable quota); type
READERorANY(console-created ones areANY); membership by a static list or an exclusion list (new instances then join automatically). - ⚠️ Changed: the maximum cluster volume is 256 TiB for Aurora MySQL 3.10+ and Aurora PostgreSQL 15.13+, 16.9+ and 17.5+ (128 TiB on earlier versions), and there is no fixed growth increment to plan around. Older material may say "128 TB maximum, grows in 10 GB increments". Watch
AuroraVolumeBytesLeftTotal. - Aurora Replicas share the cluster's encryption: no encrypted replica in an unencrypted cluster or the reverse.
- Aurora Auto Scaling: scalable dimension
rds:cluster:ReadReplicaCount; target tracking onRDSReaderAverageCPUUtilizationorRDSReaderAverageDatabaseConnections(or a custom metric); 0–15 replicas; default cooldowns 300 s; needs at least one existing reader; removes only replicas it created; never scales the writer. - ⚠️ Changed: Aurora Global Database supports up to 10 read-only secondary Regions (each with up to 16 readers), with replication typically under 1 second. Older material may say "up to 5 secondary Regions". Switchover (formerly "managed planned failover") moves the primary Region with no data loss; failover recovers from a Regional outage; optional write forwarding lets secondaries forward writes to the primary. Backtrack isn't supported in a global database, and Aurora Auto Scaling doesn't apply to secondary clusters.
- Aurora MySQL can also replicate to up to five cross-Region read replica clusters with binlog replication; Aurora PostgreSQL uses Global Database for cross-Region copies.
- Metrics:
AuroraReplicaLagandAuroraReplicaLagMaximum(milliseconds),VolumeBytesUsed,AuroraVolumeBytesLeftTotal. - Performance and price multipliers quoted on course slides ("5x MySQL, 3x PostgreSQL", "about 20 % more expensive than RDS") are marketing figures, ⚠️ unverified in current AWS documentation: never hinge an answer on them.
Developer angle
# Endpoints to put in application configuration
aws rds describe-db-clusters --db-cluster-identifier orders-aurora \
--query 'DBClusters[0].[Endpoint,ReaderEndpoint]' --output text
# A reader sized like the writer, preferred as failover target
aws rds create-db-instance --db-instance-identifier orders-aurora-r1 \
--db-cluster-identifier orders-aurora --engine aurora-postgresql \
--db-instance-class db.r7g.xlarge --promotion-tier 0
# Reporting endpoint limited to two large readers
aws rds create-db-cluster-endpoint --db-cluster-identifier orders-aurora \
--db-cluster-endpoint-identifier reporting --endpoint-type READER \
--static-members orders-aurora-r3 orders-aurora-r4
# Keep average reader CPU near 60 % with 1 to 8 readers
aws application-autoscaling register-scalable-target --service-namespace rds \
--resource-id cluster:orders-aurora --scalable-dimension rds:cluster:ReadReplicaCount \
--min-capacity 1 --max-capacity 8
aws application-autoscaling put-scaling-policy --policy-name orders-reader-cpu \
--service-namespace rds --resource-id cluster:orders-aurora \
--scalable-dimension rds:cluster:ReadReplicaCount --policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration file://reader-cpu.json
reader-cpu.json:
{
"TargetValue": 60.0,
"PredefinedMetricSpecification": { "PredefinedMetricType": "RDSReaderAverageCPUUtilization" },
"ScaleInCooldown": 600,
"ScaleOutCooldown": 300
}
- Configure two data sources: the cluster endpoint for writes and read-your-writes, the reader endpoint for the rest. Give pooled reader connections a maximum lifetime so new replicas receive traffic.
- The AWS JDBC and Python wrapper drivers track cluster topology and reconnect faster than DNS-based failover; RDS Proxy (§6) shortens failover too.
Traps
- Trap: "The reader endpoint load-balances every query." → Reality: it balances when a connection is opened.
- Trap: "The reader endpoint is always read-only." → Reality: with no replicas it lands on the writer.
- Trap: "Use instance endpoints for high availability." → Reality: they don't follow failover; use cluster, reader or custom endpoints.
- Trap: "Aurora Auto Scaling adds capacity to the writer." → Reality: it adds and removes readers only.
- Trap: "Global Database secondaries accept writes." → Reality: they are read-only unless write forwarding is on; the writer is in the primary Region.
- Trap: "Pre-size Aurora storage." → Reality: it grows and shrinks automatically, up to 128 or 256 TiB depending on the version.
- Trap: "The cheapest replica is promoted first." → Reality: promotion follows tiers, then size; give the writer-sized replica tier 0 or 1.
Practice questions
-
An Aurora MySQL cluster has a writer and four replicas. Two replicas are large instances reserved for an analytics team; the other two serve the web application. Analytics queries must never land on the web application's replicas. What should a developer configure with the LEAST operational overhead?
- A. Create a custom endpoint whose static members are the two large replicas and give it to the analytics team.
- B. Give the analytics team the reader endpoint and set the web replicas to promotion tier 15.
- C. Give the analytics team the instance endpoints of the two large replicas and have them switch hosts manually on failure.
- D. Create a second Aurora cluster for analytics and feed it with binlog replication.
-
After a writer failure, an Aurora PostgreSQL cluster promoted a small replica used for nightly reports, and the application slowed down badly until someone intervened. Next time, a writer-sized replica must take over and the reporting replica must be the last choice. Which TWO actions should the developer take? (Select TWO.)
- A. Set the promotion tier of the writer-sized replica to 0.
- B. Turn on Backtrack for the cluster.
- C. Delete the cluster's reader endpoint so that failover ignores the readers.
- D. Set the promotion tier of the reporting replica to 15.
- E. Switch the cluster to Aurora I/O-Optimized storage.
Answers
- A. A custom endpoint balances connections over exactly the listed instances and keeps working when instances fail or are replaced. B fails because the reader endpoint spreads connections over all replicas (tiers only affect failover); C pushes failover handling into clients; D adds a second cluster to run and pay for.
- A, D. Failover picks the replica with the best (lowest) tier, then the largest one, so tier 0 for the writer-sized replica and tier 15 for the reporting replica fixes the order. B rewinds data and doesn't influence failover; C isn't possible, because the built-in reader endpoint can't be deleted, and wouldn't change failover; E changes I/O billing only.
5. Aurora Serverless and the Data API
Concept
- Aurora Serverless v2 (current AWS docs simply say "Aurora serverless") is the instance class
db.serverlessinside a normal Aurora cluster. Each serverless instance scales its compute in place, in steps as small as 0.5 Aurora capacity units (ACUs) — each about 2 GiB of memory with matching CPU and networking — between the cluster'sMinCapacityandMaxCapacity. Scaling doesn't drop connections or wait for a quiet moment; you pay per ACU-hour used. - Serverless and provisioned instances can share a cluster. Readers in promotion tiers 0–1 scale with the writer (ready to take over); readers in tiers 2–15 scale on their own load.
- Auto-pause: with
MinCapacity = 0, an instance with no user connections forSecondsUntilAutoPausepauses and its compute isn't billed; the next connection resumes it in about 15 seconds. - Aurora Serverless v1, the older separate engine mode, has reached end of life.
- The RDS Data API is an HTTPS endpoint (
rds-data) that runs SQL against an Aurora cluster without a database driver, a persistent connection or VPC networking in the caller. Credentials come from a Secrets Manager secret and IAM controls who may call it. It suits Lambda functions, scripts and AWS AppSync resolvers with short statements.
Exam facts
- ⚠️ Changed: capacity ranges go up to 0–256 ACUs: 0.5–128 on older engine versions; 0.5–256 from Aurora MySQL 3.06 and Aurora PostgreSQL 13.13, 14.10, 15.5 and 16.1; 0–256 from Aurora MySQL 3.08.0 and Aurora PostgreSQL 13.15, 14.12, 15.7 and 16.3 (256 ACUs since 2024-10-03, scale to zero since 2024-11-20). Older material may say "0.5–128 ACUs; only Serverless v1 can pause".
SecondsUntilAutoPause: 300–86,400 s, default 300. Resume takes about 15 s, or 30 s and more after a pause longer than 24 hours, so client connect timeouts must exceed that and connections should be retried. A Data API call that reaches a paused instance fails withDatabaseResumingExceptionwhile the instance wakes: retry after a few seconds.- No auto-pause while user connections are open or an RDS Proxy is attached (it holds a connection to every instance). With logical or binlog replication, a zero-ETL integration, a Global Database primary or provisioned instances in the cluster, the writer and tier 0–1 readers stay awake; secondary Global Database clusters never pause. A Data API call, a parameter group change or describing log files resumes the instance.
- ⚠️ Changed: Aurora Serverless v1 reached end of life on 2025-03-31 (no new v1 clusters after 2025-01-08). Older material may say "use Aurora Serverless v1 for intermittent workloads because it pauses".
- Up to 15 serverless readers per cluster across three AZs; storage, backups and failover work as for provisioned Aurora.
max_connectionsis derived fromMaxCapacity, so connections aren't cut when capacity drops.- Metrics:
ServerlessDatabaseCapacity(current ACUs) andACUUtilization(% ofMaxCapacity). - Enabling the Data API:
--enable-http-endpointoncreate-db-cluster, oraws rds enable-http-endpoint --resource-arn <cluster-arn>for an existing cluster. - ⚠️ Changed: the Data API works with Aurora PostgreSQL and Aurora MySQL clusters that use provisioned or Aurora Serverless v2 instances (Aurora MySQL support since 2024-09-26). Older material may say "the Data API works only with Aurora Serverless v1".
- Data API operations:
ExecuteStatement,BatchExecuteStatement,BeginTransaction,CommitTransaction,RollbackTransaction. IAM:rds-data:<operation>on the cluster ARN plussecretsmanager:GetSecretValueon the secret; the managed policyAmazonRDSDataFullAccesscovers both. Missing either permission →AccessDeniedException. - Data API limits: a call times out after 45 s (
continueAfterTimeoutlets a long statement such as DDL keep running, but the caller still receives the timeout); a transaction expires after 3 minutes without a call that uses its ID and is rolled back; responses ≤ 1 MiB; HTTP requests ≤ 4 MiB; statements run only on the writer; T instance classes aren't supported. Keep SDK timeouts ≥ 60 s (the Java 2.x SDK defaults to 30 s), or an SDK retry can duplicate a write. - Without
transactionId, each statement commits on its own.
Developer angle
# Cluster that can pause after 15 idle minutes, with the Data API turned on
aws rds create-db-cluster --db-cluster-identifier events-aurora \
--engine aurora-postgresql \
--serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=16,SecondsUntilAutoPause=900 \
--master-username events_admin --manage-master-user-password \
--enable-http-endpoint
aws rds create-db-instance --db-instance-identifier events-aurora-w1 \
--db-cluster-identifier events-aurora --engine aurora-postgresql \
--db-instance-class db.serverless
Insert inside a transaction from Lambda through the Data API (no driver, no VPC attachment):
import os
import boto3
rds_data = boto3.client("rds-data")
CLUSTER_ARN = os.environ["CLUSTER_ARN"]
SECRET_ARN = os.environ["SECRET_ARN"] # secret of a dedicated application user
def handler(event, context):
tx = rds_data.begin_transaction(resourceArn=CLUSTER_ARN, secretArn=SECRET_ARN,
database="events")
try:
rds_data.execute_statement(
resourceArn=CLUSTER_ARN, secretArn=SECRET_ARN, database="events",
transactionId=tx["transactionId"],
sql="INSERT INTO signups (email, plan) VALUES (:email, :plan)",
parameters=[{"name": "email", "value": {"stringValue": event["email"]}},
{"name": "plan", "value": {"stringValue": event["plan"]}}])
rds_data.commit_transaction(resourceArn=CLUSTER_ARN, secretArn=SECRET_ARN,
transactionId=tx["transactionId"])
except Exception:
rds_data.rollback_transaction(resourceArn=CLUSTER_ARN, secretArn=SECRET_ARN,
transactionId=tx["transactionId"])
raise
return {"ok": True}
Least-privilege permissions for that function's execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["rds-data:BeginTransaction", "rds-data:ExecuteStatement",
"rds-data:CommitTransaction", "rds-data:RollbackTransaction"],
"Resource": "arn:aws:rds:eu-west-1:111122223333:cluster:events-aurora"
},
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:eu-west-1:111122223333:secret:events-app-*"
}
]
}
Traps
- Trap: "Use Aurora Serverless v1 to scale to zero." → Reality: v1 is retired; Serverless v2 pauses at 0 ACUs.
- Trap: "Put RDS Proxy in front of a pausing dev cluster." → Reality: the proxy's open connections prevent auto-pause.
- Trap: "Serverless scaling restarts the instance and drops sessions." → Reality: it scales in place without disruption.
- Trap: "A tier-15 serverless reader is ready to take over at full size." → Reality: only tiers 0–1 track the writer's capacity.
- Trap: "Run a 10-minute ETL statement through the Data API and wait for the result." → Reality: 45-second call timeout and 1 MiB responses; use a driver connection, or
continueAfterTimeoutand accept the timeout reply. - Trap: "Pass the database password in the Data API request." → Reality: pass
secretArn; the caller needssecretsmanager:GetSecretValue. - Trap: "A Lambda function must join the VPC to use the Data API." → Reality: the Data API is an AWS HTTPS endpoint (a PrivateLink endpoint is optional).
Practice questions
-
A team runs an Aurora PostgreSQL development database that is busy during working hours and idle at night and on weekends. Developers accept a delay of about 15 seconds on the first connection after an idle period. Which configuration minimizes compute cost with the LEAST operational overhead?
- A. Use Aurora Serverless v2 instances with a minimum capacity of 0 ACUs so that idle instances pause.
- B. Schedule an Amazon EventBridge rule and a Lambda function that stop the cluster every evening and start it every morning.
- C. Use the smallest burstable provisioned instance class and leave it running.
- D. Migrate the cluster to Aurora Serverless v1 so that it pauses when idle.
-
A Lambda function that isn't attached to a VPC must run short
INSERTandSELECTstatements against an Aurora MySQL cluster. The developer wants no database driver, no database password in the function's configuration, and the MOST secure setup. Which TWO actions should the developer take? (Select TWO.)- A. Store the database password in an encrypted Lambda environment variable and send it with each request.
- B. Enable the RDS Data API on the cluster with
aws rds enable-http-endpoint. - C. Grant the execution role
rds-data:ExecuteStatementon the cluster ARN andsecretsmanager:GetSecretValueon the database secret. - D. Make the cluster publicly accessible so that the function can reach it over the internet.
- E. Attach the function to the VPC and connect through an RDS Proxy with the MySQL driver.
Answers
- A. Serverless v2 at 0 ACUs pauses by itself and resumes on the next connection in about 15 seconds. B works but adds automation to build and maintain, and starting a stopped cluster is slower; C keeps paying for idle compute; D is no longer available (v1 reached end of life on 2025-03-31).
- B, C. The Data API removes the driver and connection handling, and IAM plus a Secrets Manager secret keeps passwords out of the function. A leaves a long-term password in configuration; D exposes the database; E works but needs the driver and the VPC attachment the team wants to avoid.
6. RDS Proxy
Concept
- RDS Proxy is a managed, highly available connection pooler that runs in your VPC between applications and an RDS DB instance, an Aurora cluster or a Multi-AZ DB cluster. Clients connect to the proxy endpoint; the proxy keeps a warm pool of database connections and multiplexes many client connections onto fewer database connections, reusing them at transaction boundaries.
- What it fixes: connection storms from fast-scaling clients such as Lambda, CPU and memory spent opening connections, and slow failover (the proxy follows the new writer itself instead of waiting for DNS; AWS cites failover up to 66 % faster for Aurora Multi-AZ databases). When the pool is exhausted it queues and throttles clients, then sheds load instead of letting the database collapse.
- Security: it can require TLS and IAM authentication from clients, and it reaches the database with credentials from Secrets Manager or with IAM (end-to-end IAM authentication).
- Usually no code change: replace the database host name with the proxy endpoint.
- Supported: RDS for MariaDB, MySQL, PostgreSQL and SQL Server; Aurora MySQL and Aurora PostgreSQL. Not RDS for Oracle, RDS for Db2 or RDS Custom for SQL Server.
Exam facts
- Never publicly accessible, and it must live in the database's VPC; clients in another VPC use an additional proxy endpoint created in their VPC.
- Quotas: 20 proxies per account and Region (adjustable); up to 200 Secrets Manager secrets per proxy; the default endpoint spans two AZs; up to 20 additional endpoints per proxy. Read-only proxy endpoints (
TargetRoleREAD_ONLY) work for Aurora clusters and Multi-AZ DB clusters; for RDS DB instances only the writer can be a target, not a read replica. - One proxy points at one target database; several proxies can share a database (split
MaxConnectionsPercentbetween them). Keep each proxy at or above AWS's recommended minimum, judged by the smallest registered instance: 20 on most instance classes, more on small burstable ones (RDSdb.t3.small30; Auroradb.t3.small100,db.t3.medium55,db.t3.large35). The proxy reserves some connections for monitoring and failover, andMaxDatabaseConnectionsAlloweddoesn't count them. - Pool settings and defaults:
MaxConnectionsPercent100 (10 for SQL Server) of the database'smax_connections;MaxIdleConnectionsPercenthalf of that;ConnectionBorrowTimeout120 s (0–300);IdleClientTimeout1,800 s (30 min);InitQuery;SessionPinningFilters(EXCLUDE_VARIABLE_SETS, MySQL engine family only);RequireTLS; debug (enhanced) logging turns itself off after 24 hours. A client connection lives at most 24 hours, so give application-side pools a shorter maximum lifetime. - Client authentication: IAM authentication Required or Not allowed (
IAMAuthREQUIRED/DISABLED); the console's Allowed (API valueENABLED, optional IAM) exists only for SQL Server proxies. The client signs an RDS auth token for the proxy endpoint and needsrds-db:connectonarn:aws:rds-db:<region>:<account>:dbuser:prx-<id>/<db-user>. - Proxy-to-database authentication: Secrets Manager secrets read by the proxy's IAM role (
secretsmanager:GetSecretValue, pluskms:Decryptfor the secret's key). ⚠️ Changed: since 2025-09-12 a proxy can use end-to-end IAM authentication (DefaultAuthSchemeIAM_AUTH): no secrets, the proxy role getsrds-db:connecton the database users, and IAM database authentication must be on for the target (MySQL, MariaDB and PostgreSQL engine families; not SQL Server). Older material may say "RDS Proxy always needs the database credentials in Secrets Manager". - Pinning: when a session changes state that can't be shared safely, the proxy pins the client to one database connection until it disconnects, so reuse drops. Triggers include session variables set with
SET(on MySQL and MariaDB the proxy tracks a short list, such astime_zone,sql_mode,autocommitand the character-set variables, plus theUSEstatement, without pinning), temporary tables, prepared statements andLOCK TABLES/GET_LOCKon MySQL;SET,PREPARE, cursors,LISTENand advisory locks on PostgreSQL; and any statement over 16 KB. WatchDatabaseConnectionsCurrentlySessionPinned; move repeatedSETstatements intoInitQuery, or add a session pinning filter when the application tolerates it. - TLS to the proxy uses AWS Certificate Manager certificates, so clients don't need the RDS CA bundle for the proxy itself.
- The proxy listens on 3306 for the MySQL family and 5432 for PostgreSQL, whatever port the database uses.
- Metrics (namespace
AWS/RDS, dimensionProxyName):ClientConnections,DatabaseConnections,MaxDatabaseConnectionsAllowed,DatabaseConnectionsBorrowLatency,DatabaseConnectionsCurrentlySessionPinned,QueryRequests. - Because the proxy keeps connections open, Aurora Serverless v2 instances behind it never auto-pause (§5). RDS Proxy doesn't support global condition context keys in IAM policies.
- Lambda pattern: the function runs in private subnets of the same VPC (
notes/lambda-guide.md§10); the proxy's security group admits the function's security group on the engine port and the database's security group admits the proxy's; open the connection outside the handler so warm invocations reuse it. Reserved concurrency (notes/lambda-guide.md§5) is the alternative when throttling the function is acceptable.
Developer angle
aws rds create-db-proxy --db-proxy-name orders-proxy --engine-family POSTGRESQL \
--role-arn arn:aws:iam::111122223333:role/orders-proxy-secrets \
--vpc-subnet-ids subnet-0aaa1111bbbb2222c subnet-0ddd3333eeee4444f \
--vpc-security-group-ids sg-0aa11bb22cc33dd44 \
--auth '[{"AuthScheme":"SECRETS","SecretArn":"arn:aws:secretsmanager:eu-west-1:111122223333:secret:orders-app-AbCdEf","IAMAuth":"REQUIRED"}]' \
--require-tls --idle-client-timeout 900
aws rds register-db-proxy-targets --db-proxy-name orders-proxy \
--target-group-name default --db-instance-identifiers orders-db
aws rds modify-db-proxy-target-group --db-proxy-name orders-proxy --target-group-name default \
--connection-pool-config MaxConnectionsPercent=80,MaxIdleConnectionsPercent=40,ConnectionBorrowTimeout=60
Lambda handler that signs in to the proxy with its execution role (no stored password):
import os
import boto3
import psycopg2
PROXY_HOST = os.environ["PROXY_ENDPOINT"]
DB_USER = os.environ["DB_USER"]
_conn = None # reused by warm invocations
def _connect():
token = boto3.client("rds").generate_db_auth_token(
DBHostname=PROXY_HOST, Port=5432, DBUsername=DB_USER,
Region=os.environ["AWS_REGION"])
return psycopg2.connect(host=PROXY_HOST, port=5432, dbname="orders",
user=DB_USER, password=token, sslmode="require")
def handler(event, context):
global _conn
if _conn is None or _conn.closed:
_conn = _connect()
with _conn.cursor() as cur:
cur.execute("SELECT status FROM orders WHERE id = %s", (event["orderId"],))
row = cur.fetchone()
_conn.commit()
return {"status": row[0] if row else None}
Execution-role permission for that token:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "rds-db:connect",
"Resource": "arn:aws:rds-db:eu-west-1:111122223333:dbuser:prx-0123456789abcdef0/orders_app"
}]
}
Traps
- Trap: "Make the proxy public so laptops can use it." → Reality: a proxy can't be made publicly accessible; reach it from inside the VPC (or through an extra proxy endpoint in another VPC).
- Trap: "RDS Proxy speeds up slow queries." → Reality: it manages connections; fix the query, add replicas or cache.
- Trap: "Put the proxy in front of an RDS read replica." → Reality: RDS instance targets are writers only; read-only proxy endpoints exist for Aurora and Multi-AZ DB clusters.
- Trap: "Clients need the RDS CA bundle to verify the proxy." → Reality: the proxy presents ACM certificates.
- Trap: "Run
SETat the start of every request; the proxy copes." → Reality: anySEToutside the short tracked list pins the session; move it intoInitQuery. - Trap: "RDS Proxy works with every engine." → Reality: not with Oracle or Db2.
- Trap: "End-to-end IAM still needs one secret per database user." → Reality: with
IAM_AUTHthe proxy signs in to the database with IAM; secrets become optional.
Practice questions
-
A serverless API uses AWS Lambda functions that query an Amazon RDS for MySQL instance. During traffic spikes the database returns
Too many connectionserrors, and CPU climbs while connections are being opened. The team must keep serving the spike and wants the fewest code changes. What should a developer do?- A. Set a low reserved concurrency value on every function that queries the database.
- B. Move the DB instance to a class with twice the memory and vCPUs.
- C. Cache every query result in Amazon ElastiCache before calling the database.
- D. Put an RDS Proxy in front of the instance and point the functions at its endpoint.
-
An RDS Proxy in front of an Aurora MySQL cluster reports a high
DatabaseConnectionsCurrentlySessionPinnedvalue, and connection reuse is poor. The application runsSET SESSION group_concat_max_len = 1000000at the start of every request. Which TWO changes would improve multiplexing? (Select TWO.)- A. Raise
MaxConnectionsPercentto 100. - B. Increase the idle client connection timeout to 8 hours.
- C. Turn off
RequireTLSon the proxy. - D. Move the
SETstatement into the proxy's initialization query and remove it from the application. - E. Add the
EXCLUDE_VARIABLE_SETSsession pinning filter after confirming that the application doesn't rely on session variables set outside the current transaction.
- A. Raise
Answers
- D. The proxy pools and reuses connections, absorbs the burst and needs only a host-name change. A protects the database by throttling requests, which fails the "keep serving the spike" requirement; B costs more and still lets connection storms grow; C needs substantial code changes.
- D, E.
group_concat_max_lenisn't one of the variables the proxy tracks, so every request pins its session. An initialization query gives every pooled connection the same setting without pinning, and the session pinning filter exempts variableSETs for MySQL-family proxies when that is safe. A adds connections but doesn't stop pinning; B keeps idle clients longer and worsens reuse; C doesn't affect pinning and weakens security.
7. Encryption and IAM database authentication
Concept
- At rest: RDS and Aurora encrypt storage, logs, automated backups, snapshots and replicas with AES-256 under an AWS KMS key — the AWS managed key
aws/rdsor a customer managed key (Aurora can also use an AWS owned key). Encryption is transparent to applications. KMS key types and policies:notes/security-encryption-guide.md§1–§2. - RDS DB instances get encryption only if you choose it at creation (the API default is unencrypted). Aurora clusters created on or after 2026-02-18 are encrypted by default.
- In transit: clients connect with TLS and verify the server certificate against the RDS root CA bundle; a parameter can reject unencrypted connections.
- IAM database authentication replaces the database password with a short-lived token: code holding IAM credentials (instance profile, Lambda execution role, ECS task role) asks the SDK for a token — a SigV4-signed request valid for 15 minutes — and presents it as the password over TLS. Access is granted in IAM with
rds-db:connect. - Secrets Manager is the alternative when passwords stay (managed rotation, RDS-managed master secrets):
notes/security-encryption-guide.md§10–§11.
Exam facts
- An existing unencrypted RDS DB instance can't be encrypted in place, encryption can't be switched off, and the KMS key can't be changed in place. Classic path: snapshot →
copy-db-snapshot --kms-key-id(encrypted copy) → restore a new instance → repoint the application. - ⚠️ Changed: a blue/green deployment can also build a green environment encrypted with a different KMS key (
TargetKmsKeyIdinTargetResourceConfigurationsofCreateBlueGreenDeployment), which encrypts an unencrypted database or changes its key with a short switchover. Older material may say "snapshot copy and restore is the only way". - RDS: an unencrypted snapshot can't be restored straight into an encrypted instance (copy it encrypted first). Aurora: an unencrypted snapshot can be restored into an encrypted cluster by naming a KMS key during the restore; since the 2026-02-18 default, a restore without a key also comes back encrypted (AWS owned key).
- ⚠️ Changed: Aurora clusters created on or after 2026-02-18 are encrypted at rest by default with an AWS owned key (pick an AWS managed or customer managed key if you need control); clones, snapshot copies and replicas of older unencrypted clusters stay unencrypted. Older material may say "Aurora is unencrypted unless you turn encryption on at launch".
- Replicas match the source's encryption state; a cross-Region replica or snapshot copy needs a KMS key in the destination Region.
- Snapshots encrypted with
aws/rdscan't be shared: re-encrypt with a customer managed key and allow the other account in its key policy (§8). - A disabled KMS key sends the database to
inaccessible-encryption-credentials-recoverable(stopped; recover within 7 days by re-enabling the key and starting it), then to the terminalinaccessible-encryption-credentialsstate (restore from a backup). Instances that can't be stopped — read replicas and sources of replicas — go straight to the terminal state; RDS then tries to take a finalrds-final:snapshot. - Traffic between a source and its replicas is encrypted in transit even for unencrypted databases.
- TLS: CAs
rds-ca-rsa2048-g1(default),rds-ca-rsa4096-g1andrds-ca-ecc384-g1; RDS rotates server certificates automatically; trust only the root bundle (global-bundle.pemor a Regional bundle); change the CA with--ca-certificate-identifier. ⚠️ Changed: the default CA isrds-ca-rsa2048-g1. Older material may namerds-ca-2019. - Forcing TLS: PostgreSQL
rds.force_ssl = 1(non-TLS clients getno pg_hba.conf entry … SSL off). ⚠️ Changed: that is already the default on RDS for PostgreSQL 15 and later (0 on 14 and earlier). Older material may say "PostgreSQL accepts unencrypted connections until you setrds.force_ssl". MySQL:require_secure_transport = ON(defaultOFF, dynamic, no reboot; insecure clients get error 3159). - IAM DB auth engines: RDS for MariaDB, MySQL and PostgreSQL; Aurora MySQL and Aurora PostgreSQL; Multi-AZ DB clusters. Turn it on with
--enable-iam-database-authentication(create, modify or restore; restores inherit the snapshot's setting); a modification waits for the maintenance window unless you add--apply-immediately. - Map database users: MySQL/MariaDB
CREATE USER 'app_user' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';(Plugin 'AWSAuthenticationPlugin' is not loadedmeans IAM auth isn't on or supported); PostgreSQLGRANT rds_iam TO app_user;(IAM then takes precedence over that user's password). - Policy: action
rds-db:connect(not anrds:action) onarn:aws:rds-db:<region>:<account>:dbuser:<DbiResourceId>/<db-user>. The resource ID (db-…) isn't the instance name (describe-db-instances→DbiResourceId); Aurora uses the cluster resource ID; through a proxy useprx-…. Wildcards such asdbuser:*/report_*work. - The token only authenticates the login: an open session survives its 15-minute lifetime, but each new connection needs a fresh token. Generate it for the real RDS endpoint (not a custom Route 53 name); temporary signing credentials must still be valid when you connect.
- Limits: plan 300–1,000 MiB of extra database memory; token generation isn't logged by CloudWatch or CloudTrail (use the metric
IamDbAuthConnectionRequestsand theiam-db-auth-errorlog export); conditions onaws:SourceIp,aws:SourceVpc,aws:SourceVpce,aws:VpcSourceIp,aws:UserAgentandaws:Refereraren't supported. ⚠️ Changed: current docs set no connection-rate ceiling. Older material may say "use IAM database authentication only below 200 new connections per second". For very high connection rates, connect through RDS Proxy. - RDS for PostgreSQL and Aurora PostgreSQL can make the master user itself IAM-authenticated (
--master-user-authentication-type iam-db-auth).
Developer angle
# Encrypt an existing unencrypted instance with a customer managed key
aws rds create-db-snapshot --db-instance-identifier legacy-db \
--db-snapshot-identifier legacy-db-plain
aws rds copy-db-snapshot --source-db-snapshot-identifier legacy-db-plain \
--target-db-snapshot-identifier legacy-db-encrypted --kms-key-id alias/orders-rds
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier legacy-db-v2 \
--db-snapshot-identifier legacy-db-encrypted
# Turn on IAM database authentication now, and refuse non-TLS clients on a MySQL instance
aws rds modify-db-instance --db-instance-identifier catalog-db \
--enable-iam-database-authentication --apply-immediately
aws rds modify-db-parameter-group --db-parameter-group-name catalog-mysql80 \
--parameters "ParameterName=require_secure_transport,ParameterValue=ON,ApplyMethod=immediate"
# Resource ID for the rds-db:connect ARN
aws rds describe-db-instances --db-instance-identifier orders-db \
--query 'DBInstances[0].DbiResourceId' --output text
Token-based login from code that runs with an IAM role:
import boto3
import psycopg2
HOST = "orders-db.abcdefghij12.eu-west-1.rds.amazonaws.com"
def connect_with_iam(user: str):
token = boto3.client("rds", region_name="eu-west-1").generate_db_auth_token(
DBHostname=HOST, Port=5432, DBUsername=user)
return psycopg2.connect(host=HOST, port=5432, dbname="orders", user=user,
password=token, sslmode="verify-full",
sslrootcert="/opt/certs/global-bundle.pem")
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "rds-db:connect",
"Resource": "arn:aws:rds-db:eu-west-1:111122223333:dbuser:db-ABCDEFGHIJKL01234/app_user"
}]
}
Traps
- Trap: "
modify-db-instance --storage-encryptedencrypts the running database." → Reality: use an encrypted snapshot copy and restore, or a blue/green deployment. - Trap: "Create an encrypted read replica of the unencrypted primary, then promote it." → Reality: replicas must match the source's encryption state.
- Trap: "Grant
rds:Connecton the DB instance ARN." → Reality: the action isrds-db:connecton adbuserARN built from the resource ID. - Trap: "Put the instance identifier in the
dbuserARN." → Reality: useDbiResourceId(or the cluster or proxy resource ID). - Trap: "The token is a password that lasts all day." → Reality: new logins need a token younger than 15 minutes.
- Trap: "Limit IAM database logins with
aws:SourceIp." → Reality: that condition key isn't supported for IAM DB auth. - Trap: "IAM authentication works over plain TCP." → Reality: it requires SSL/TLS.
Practice questions
-
Compliance requires an existing, unencrypted Amazon RDS for MySQL instance to be encrypted at rest with a customer managed AWS KMS key. Which approach meets the requirement?
- A. Run
modify-db-instancewith--storage-encryptedand--kms-key-id, and apply the change immediately. - B. Create an encrypted read replica with the customer managed key and promote it.
- C. Snapshot the instance, copy the snapshot with
--kms-key-idset to the key, and restore a new instance from the copy. - D. Set
require_secure_transporttoONin the instance's parameter group.
- A. Run
-
A developer is moving an application on Amazon EC2 to IAM database authentication for an Amazon RDS for PostgreSQL instance so that no database password is stored anywhere. Which TWO steps are required? (Select TWO.)
- A. Store the database password in the instance's user data so that the SDK can sign requests.
- B. Enable IAM database authentication on the instance and
GRANT rds_iamto the application's database user. - C. Attach a policy to the instance's IAM role that allows
rds:Connecton the DB instance ARN. - D. Set
rds.force_sslto 0 so that the token can be sent without TLS. - E. Attach a policy to the instance's IAM role that allows
rds-db:connectonarn:aws:rds-db:<region>:<account>:dbuser:<DbiResourceId>/<db-user>.
Answers
- C. Encryption can't be switched on in place, so the supported path is an encrypted snapshot copy restored as a new instance (then repoint the application). A fails because existing instances can't be encrypted by modification; B fails because a replica of an unencrypted source can't be encrypted; D concerns encryption in transit, not at rest.
- B, E. The database must accept IAM tokens for that user, and the role needs
rds-db:connecton thedbuserresource. A stores a plaintext secret and isn't how tokens work; C names an action that doesn't exist for database logins; D is wrong because IAM database authentication requires TLS.
8. Backups snapshots and restores
Concept
- Automated backups (RDS): a daily storage-volume snapshot taken in the backup window plus transaction logs shipped to S3 every 5 minutes, so you can restore to any second inside the retention period (the latest restorable time is usually within about 5 minutes of now).
- Manual snapshots are taken on request and kept until you delete them — they survive deletion of the instance — and can be copied to other Regions and shared with other accounts.
- Every restore creates a new DB instance or cluster with a new endpoint. Update the application's configuration (or rename instances) afterwards.
- Aurora backs up continuously and incrementally with no performance impact, and adds two developer tools: Backtrack (Aurora MySQL only) rewinds the existing cluster in place within minutes, and cloning creates a copy-on-write copy of a cluster quickly and cheaply for tests.
- Deleting a database offers a final snapshot and the option to retain automated backups; deletion protection blocks accidental deletes.
Exam facts
- RDS retention: 0–35 days; default 7 days from the console and 1 day from the API/CLI; 0 disables automated backups and PITR and isn't allowed while the instance has read replicas; switching between 0 and a non-zero value causes an outage. Multi-AZ DB clusters: 1–35 days.
- Aurora retention: 1–35 days, default 1 day however the cluster is created; automated backups can't be turned off; cluster snapshots don't expire. The default backup window (RDS and Aurora) is a 30-minute slot picked at random from an 8-hour block for the Region and can't overlap the maintenance window.
- On a Single-AZ RDS instance a snapshot briefly suspends I/O (about a second); a Multi-AZ DB instance takes it from the standby.
- Quota: 100 manual DB snapshots per Region (adjustable); snapshots made by AWS Backup don't count toward it.
- Restore details: default parameter and option groups unless you pass custom ones; the default VPC security group (and DB subnet group) unless you pass others, for example
--vpc-security-group-ids; storage can't shrink; the IAM DB auth setting follows the snapshot unless overridden; restored volumes load blocks from S3 lazily, so first reads can be slow (StorageOperationStatus=Initializingwhile hydrating). - Aurora restores and clones made with the CLI or API create the cluster without instances: call
create-db-instancefor the writer, or the cluster endpoints stay increating. - Copying: automated snapshots can be copied (the copy is a manual snapshot); cross-Region copies run in the destination Region with the source ARN, need a destination-Region KMS key when encrypted, pay data transfer, and are limited to 20 in progress per destination Region; Multi-AZ DB cluster snapshots can't be copied.
- Sharing (RDS): manual snapshots only (copy an automated one first); up to 20 accounts;
modify-db-snapshot-attribute --attribute-name restore --values-to-add <account>; the valueallmakes it public (unencrypted snapshots only); encrypted snapshots need a customer managed key whose key policy allows the other account —aws/rdssnapshots must be copied with a customer managed key first; the receiving account copies a shared encrypted DB snapshot before restoring it; restore a shared snapshot by its ARN. Multi-AZ DB cluster snapshots can't be shared. Shared Aurora cluster snapshots (encrypted or not) can be restored directly. - Backtrack: Aurora MySQL (versions 2, 3 and 8.4) only, not Aurora PostgreSQL; set
--backtrack-window(seconds, up to 72 hours) when you create the cluster or restore a snapshot, never later; rewinds the whole cluster in place; briefly pauses the database and closes connections; not with cross-Region read replicas or Global Database; you pay for stored change records. - Cloning: copy-on-write, so it's fast and only changed pages cost extra storage; up to 15 copy-on-write clones per source (later clones become full copies); same Region only; cross-account through AWS RAM; created with
restore-db-cluster-to-point-in-time --restore-type copy-on-write. - Infrastructure as code:
DeletionPolicy: SnapshotonAWS::RDS::DBInstance/AWS::RDS::DBCluster(notes/cloudformation-guide.md§9).
Developer angle
# Manual snapshot before a risky migration, then share it with a partner account
aws rds create-db-snapshot --db-instance-identifier orders-db \
--db-snapshot-identifier orders-before-migration
aws rds modify-db-snapshot-attribute --db-snapshot-identifier orders-before-migration \
--attribute-name restore --values-to-add 444455556666
# Disaster-recovery copy in another Region (run in the destination Region)
aws rds copy-db-snapshot --region eu-central-1 \
--source-db-snapshot-identifier arn:aws:rds:eu-west-1:111122223333:snapshot:orders-before-migration \
--target-db-snapshot-identifier orders-before-migration-fra --kms-key-id alias/orders-rds-fra
# Point-in-time restore into a NEW instance, then repoint the application
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier orders-db \
--target-db-instance-identifier orders-db-restored \
--restore-time 2026-10-12T08:55:00Z \
--db-parameter-group-name orders-pg16 --vpc-security-group-ids sg-0db1234567890abcd
# Aurora MySQL with Backtrack enabled at creation: rewind the existing cluster
aws rds backtrack-db-cluster --db-cluster-identifier shop-aurora \
--backtrack-to 2026-10-12T08:55:00Z
# Aurora copy-on-write clone for a test environment, then its writer instance
aws rds restore-db-cluster-to-point-in-time --source-db-cluster-identifier shop-aurora \
--db-cluster-identifier shop-aurora-test --restore-type copy-on-write \
--use-latest-restorable-time
aws rds create-db-instance --db-instance-identifier shop-aurora-test-w1 \
--db-cluster-identifier shop-aurora-test --engine aurora-mysql \
--db-instance-class db.r7g.large
Traps
- Trap: "A restore overwrites the existing instance." → Reality: it creates a new instance or cluster with a new endpoint.
- Trap: "Share the automated snapshot with the auditors' account." → Reality: copy it to a manual snapshot first, then share.
- Trap: "Set backup retention to 0 to save money." → Reality: no PITR, an outage during the change, and no read replicas.
- Trap: "Backtrack the Aurora PostgreSQL cluster." → Reality: Backtrack exists only for Aurora MySQL.
- Trap: "Turn Backtrack on for the existing cluster now." → Reality: only at creation or when restoring a snapshot.
- Trap: "Take frequent snapshots to make Aurora PITR fine-grained." → Reality: Aurora backups are already continuous.
- Trap: "A clone duplicates all the data up front." → Reality: copy-on-write; only changed pages use new storage.
- Trap: "Manual snapshots disappear with the instance." → Reality: they stay until you delete them.
Practice questions
-
A developer accidentally ran a
DELETEwithout aWHEREclause on an Aurora MySQL production cluster 20 minutes ago. The cluster was created with a 24-hour backtrack window. The team wants the data back as fast as possible and doesn't want to change any connection strings. What should the developer do?- A. Restore the cluster to a point in time before the
DELETEand switch the application to the new cluster endpoint. - B. Run
aws rds backtrack-db-clusterwith a--backtrack-totime just before theDELETE. - C. Restore the most recent manual cluster snapshot into a new cluster.
- D. Create a copy-on-write clone of the cluster and copy the deleted rows back from it.
- A. Restore the cluster to a point in time before the
-
A company must give a partner's AWS account a copy of an encrypted Amazon RDS for PostgreSQL database. The snapshot is encrypted with the AWS managed key
aws/rds. Which TWO actions are required? (Select TWO.)- A. Make the snapshot public by adding the value
allto itsrestoreattribute. - B. Share the automated snapshot directly, because automated snapshots inherit the instance's sharing settings.
- C. Copy the snapshot with
--kms-key-idset to a customer managed key, and allow the partner account to use that key in its key policy. - D. Share the copied manual snapshot with
modify-db-snapshot-attribute --attribute-name restore --values-to-addand the partner's account ID. - E. Add the partner account to the key policy of the
aws/rdskey.
- A. Make the snapshot public by adding the value
Answers
- B. Backtrack rewinds the same cluster in place within minutes, so endpoints don't change. A and C create new clusters (new endpoints, slower); D leaves the developer copying data by hand and still adds a cluster.
- C, D. Snapshots encrypted with
aws/rdscan't be shared, so re-encrypt a copy with a customer managed key the partner may use, then share that manual snapshot. A is impossible for encrypted snapshots and would expose the data to everyone; B fails because automated snapshots can't be shared; E fails because AWS managed key policies can't be edited.
9. ElastiCache engines and MemoryDB
Concept
- Amazon ElastiCache is a managed in-memory data store used as a cache in front of databases (microsecond reads, less database load), as a session store, and for leaderboards, counters and rate limits. Unlike DAX, it doesn't plug into a database by itself: your code decides what to cache and when to refresh it.
- Engines: Valkey (open-source fork of Redis OSS; the cheaper default choice), Redis OSS and Memcached.
- Deployment options:
- ElastiCache Serverless: create a cache with only a name; it scales compute, memory and network automatically, replicates across three AZs (99.99 % SLA), always encrypts in transit and at rest, and bills per GB-hour of data plus ElastiCache Processing Units (ECPUs).
- Node-based clusters: you choose the node type, number of shards and replicas, and AZ placement, and you get parameter groups, Global Datastore, data tiering, reserved nodes and (Valkey 9.0+) durability.
| Need | Valkey / Redis OSS | Memcached |
|---|---|---|
| Data types | Strings, hashes, lists, sets, sorted sets, streams, geospatial, JSON | Simple strings and objects |
| Replication and automatic failover | Yes: 1 primary + up to 5 replicas per shard | No: a lost node loses its data |
| Backup and restore | Yes (.rdb snapshots) |
Serverless caches only |
| Scaling out | Shards (cluster mode enabled) | More nodes; the client partitions keys |
| Multi-threaded engine | No | Yes |
| Pub/Sub, sorted-set rankings | Yes | No |
- Amazon MemoryDB is a durable, in-memory primary database (Valkey- and Redis OSS-compatible) that records every write in a Multi-AZ transactional log: microsecond reads, single-digit-millisecond writes, and data that survives node failures. Choose it when the in-memory store is the system of record; choose ElastiCache to accelerate another database.
Exam facts
- ⚠️ Changed: ElastiCache works with Valkey, Memcached and Redis OSS; Valkey support since 2024-10-08 (serverless priced 33 % lower and node-based 20 % lower than the other engines; zero-downtime upgrade from Redis OSS); Valkey 9.1 is the newest engine version (its release date is ⚠️ unverified). Older material may say "ElastiCache runs Redis or Memcached".
- Serverless: Valkey 7.2+, Redis OSS 7.1, Memcached 1.6.22+; runs Valkey/Redis OSS in cluster mode enabled only (clients must be cluster-aware) behind a single endpoint; TLS always (clients must support TLS); encryption at rest always; Valkey/Redis OSS authenticate only through RBAC (no AUTH token; the user group is optional except on a public endpoint; Memcached has no RBAC); up to 40 serverless caches per Region and 24 snapshots per day per cache.
- ⚠️ Changed: ElastiCache Serverless for Valkey 9.0+ can have a public endpoint — reachable over the internet without a VPC, with IAM authentication and TLS 1.3 required for every connection, so every user in its user group must be an IAM user (documented 2026-09-29). Older material may say "ElastiCache is reachable only from inside its VPC". Node-based clusters and VPC-type serverless caches stay VPC-only: security group rules on 6379 (Valkey/Redis OSS) or 11211 (Memcached), and Lambda functions must be VPC-attached.
- Node-based Valkey/Redis OSS: cluster mode disabled = one shard, 1 primary + up to 5 replicas, a primary endpoint for writes and a reader endpoint for reads; cluster mode enabled = up to 500 shards (default quota 90 nodes per cluster; up to 500 for Valkey 7.2+/Redis OSS 5.0.6+) behind a configuration endpoint. Replication is asynchronous; Multi-AZ with automatic failover promotes the replica with the least lag.
- Memcached: 1–60 nodes per cluster (quota 60); Auto Discovery lets clients find every node; without replication, spreading data over more nodes and AZs only limits how much one failure loses; TLS from version 1.6.12.
- ⚠️ Changed: append-only file persistence (
appendonly,appendfsync) isn't supported (from Redis OSS 2.8.22, and never with Multi-AZ); protect data with Multi-AZ replicas and.rdbsnapshots, or with durability on Valkey 9.0+. Older material may say "Redis gives durability through AOF persistence". - Durability (node-based Valkey 9.0+, cluster mode enabled, Multi-AZ with at least one replica per shard, Graviton R/M/C node families): a Multi-AZ transactional log with synchronous writes (zero data loss, single-digit-ms write latency) or asynchronous writes (microsecond writes, up to 10 s of data at risk). Chosen at creation; you can switch between the two modes but never turn it off; not with serverless, Global Datastore or data tiering; turns on encryption at rest; ≤ 100 MiB/s of writes per primary.
- Authentication (Valkey/Redis OSS): the AUTH token (node-based only; needs in-transit encryption; 16–128 printable characters; rotate with
--auth-token-update-strategy ROTATE, thenSET) is superseded by RBAC: users with access strings, grouped in user groups (up to 100 users per group, one user group per replication group). IAM authentication (Valkey 7.2+/Redis OSS 7.0+): an RBAC user with authentication modeiamwhose user name equals its user ID, TLS required, the caller needselasticache:Connecton the cache and user ARNs, the token lasts 15 minutes, and IAM-authenticated connections are dropped after 12 hours unless re-authenticated withAUTH/HELLO. - Encryption in transit can be turned on for existing Valkey/Redis OSS clusters; encryption at rest uses KMS (AWS managed or customer managed key).
- Memory: default
maxmemory-policyisvolatile-lru(§10);reserved-memory-percentdefaults to 25. - Scaling: node-based Valkey/Redis OSS scale up (node type), out (shards, online resharding) and in replicas, also through Application Auto Scaling; Memcached adds nodes, with on-demand vertical and automated horizontal scaling since 2025-04-10.
- Global Datastore (node-based Valkey/Redis OSS): cross-Region replication with writes in one primary Region.
- ⚠️ Changed: the service is now Amazon MemoryDB, compatible with Valkey and Redis OSS (Valkey since 2024-10-08, priced 30 % below MemoryDB for Redis OSS, with the first 10 TB of data written per month free). Older material may say "Amazon MemoryDB for Redis".
- MemoryDB scale figures are marketing: the product page currently says "hundreds of millions of requests per second and over one hundred terabytes of storage per cluster"; the course's "over 160 million requests per second" is ⚠️ unverified.
- DAX vs ElastiCache for DynamoDB workloads:
notes/dynamodb-guide.md§10.
Developer angle
# Serverless Valkey cache inside the VPC
aws elasticache create-serverless-cache --serverless-cache-name sessions \
--engine valkey \
--subnet-ids subnet-0aaa1111bbbb2222c subnet-0ddd3333eeee4444f \
--security-group-ids sg-0cache123456789ab
aws elasticache describe-serverless-caches --serverless-cache-name sessions \
--query 'ServerlessCaches[0].Endpoint'
# Node-based Valkey: 1 primary + 2 replicas, Multi-AZ failover, TLS and at-rest encryption
aws elasticache create-replication-group --replication-group-id catalog-cache \
--replication-group-description "catalog read cache" --engine valkey \
--cache-node-type cache.r7g.large --num-node-groups 1 --replicas-per-node-group 2 \
--multi-az-enabled --automatic-failover-enabled \
--transit-encryption-enabled --at-rest-encryption-enabled \
--cache-subnet-group-name app-private
# IAM-authenticated RBAC user that may only touch session keys
aws elasticache create-user --user-id sessions-app --user-name sessions-app \
--engine valkey --authentication-mode Type=iam \
--access-string "on ~session:* -@all +get +set +del +expire"
Put the user into a user group (a VALKEY-engine group needs no default user because ElastiCache turns it off; a Redis OSS-engine group always contains one, so swap the open built-in default for a disabled user named default), attach the group to the cache, and grant the application role:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "elasticache:Connect",
"Resource": [
"arn:aws:elasticache:eu-west-1:111122223333:serverlesscache:sessions",
"arn:aws:elasticache:eu-west-1:111122223333:user:sessions-app"
]
}]
}
Valkey GLIDE 2.2+ generates and refreshes IAM tokens itself; with other clients, sign a fresh token (SigV4 presigned connect request) before the 15-minute expiry and send it as the password over TLS.
Traps
- Trap: "Use Memcached when the cache must survive a node failure." → Reality: Memcached has no replication or failover; use Valkey/Redis OSS with Multi-AZ replicas.
- Trap: "Turn on AOF for durability." → Reality: AOF isn't supported; use replicas and snapshots, Valkey 9.0+ durability, or MemoryDB.
- Trap: "Protect a serverless cache with an AUTH token." → Reality: AUTH tokens are node-based only; serverless Valkey/Redis OSS caches authenticate only through RBAC users.
- Trap: "ElastiCache caches DynamoDB reads without code changes." → Reality: that is DAX; ElastiCache needs caching code.
- Trap: "Any Redis client can talk to ElastiCache Serverless." → Reality: the client must support TLS and cluster mode.
- Trap: "An IAM-authenticated connection stays open indefinitely." → Reality: it is dropped after 12 hours unless re-authenticated.
- Trap: "MemoryDB is just a bigger cache." → Reality: it's a durable primary database with a Multi-AZ transactional log.
Practice questions
-
A gaming company needs a game-wide leaderboard that returns the top 100 players in microseconds, survives the loss of a node or an AZ, and requires the LEAST operational overhead. Which solution meets these requirements?
- A. An Amazon ElastiCache for Memcached cluster with nodes in three Availability Zones.
- B. An Amazon RDS for MySQL read replica queried with
ORDER BY score DESC LIMIT 100. - C. An Amazon DynamoDB table fronted by DAX, scanning all player scores and sorting them in the application.
- D. An Amazon ElastiCache Serverless for Valkey cache that stores scores in a sorted set.
-
A payments team wants an in-memory, Valkey-compatible data store as its system of record. Writes that were acknowledged must never be lost when a node fails. Which TWO options meet the requirement? (Select TWO.)
- A. Amazon MemoryDB.
- B. An Amazon ElastiCache Serverless for Valkey cache with daily automatic snapshots.
- C. An Amazon ElastiCache for Memcached cluster with twice as many nodes.
- D. A node-based Amazon ElastiCache for Redis OSS cluster with
appendonlyset toyesin its parameter group. - E. A node-based Amazon ElastiCache for Valkey 9.0 cluster with cluster mode enabled, Multi-AZ replicas and durability set to synchronous writes.
Answers
- D. Sorted sets give ranked reads in microseconds, and a serverless cache is replicated across three AZs with no capacity to manage. A fails because Memcached has no sorted sets or replication; B adds database latency and load; C scans the whole table on every request.
- A, E. MemoryDB is durable by design, and Valkey 9.0+ node-based clusters can keep a synchronous Multi-AZ transactional log with zero data loss. B fails because a snapshot holds data only up to the last backup (serverless caches offer no durability option); D fails because ElastiCache doesn't support append-only files; C still loses data when a node fails.
10. Caching strategies TTL and session stores
Concept
- Lazy loading (cache-aside): read the cache first; on a miss, read the database and put the result into the cache. Only data someone asked for is cached, and a failed cache node only costs latency while it refills — but every miss costs three trips (cache, database, cache write) and cached entries go stale when the database changes underneath them.
- Write-through: the code that writes the database also writes the cache. Cached data stays current and reads stay fast; the price moves to writes (two writes per update), rarely read data still occupies memory (churn), and a new or replaced node lacks data until it is written again — so combine it with lazy loading.
- TTL: an expiry on each key removes stale or unused entries automatically; reading an expired key behaves like a miss. A common mix: write-through for hot data that changes, lazy loading for everything else, and a TTL on every key, with a little random jitter so many keys don't expire at the same moment.
- Invalidation: when you can't write the new value, delete the cached key (
DEL) in the same code path that changes the database. - Eviction: when memory is full, the engine drops keys according to
maxmemory-policy. Steady evictions mean the cache is too small for the working set or keys live too long. - Session store: keep web session state in a shared cache (or DynamoDB) rather than in one server's memory, so any instance can serve any request and the web tier stays stateless (no sticky sessions needed).
- Cache what is read often and changes slowly (catalog entries, profiles, computed aggregates); don't cache values that change on every request or must always be exact (account balances).
Exam facts
- Lazy loading: miss penalty of three round trips, possible stale reads, resilient to node loss. Write-through: write penalty of two writes, fresh data, missing data on new nodes, churn.
- ⚠️ Changed: AWS's ElastiCache guidance puts a TTL on every write, write-through included, so unread entries expire instead of piling up. Older material may say "skip TTLs when you use write-through".
- TTL units: Valkey/Redis OSS accept seconds or milliseconds (
SET key value EX 300,PX 300000,EXPIRE, inspect withTTL); Memcached uses seconds. Valkey 9.0+ can also expire individual hash fields. - ElastiCache Valkey/Redis OSS default
maxmemory-policy:volatile-lru— evicts only keys that have a TTL. If no key has a TTL and memory fills, writes fail withOOM command not allowed when used memory > 'maxmemory'. Alternatives:allkeys-lru,allkeys-lfu,volatile-lfu,volatile-ttl,allkeys-random,volatile-random,noeviction. Change it in a custom parameter group (default parameter groups can't be modified; serverless caches have no parameter groups). - Metrics:
CacheHits,CacheMisses,CacheHitRate(below about 0.8 means many keys were evicted, expired or never cached),Evictions,CurrItems,CurrVolatileItems(keys with a TTL),Reclaimed(expired keys),DatabaseMemoryUsagePercentage,EngineCPUUtilization,CurrConnections. - High
Evictionswith near-100 % memory → scale up (larger nodes) or out (more shards), cache less, or shorten TTLs. - Stale reads with lazy loading → add a TTL, or update/invalidate the key when the source row changes.
- Session store: one key per session with an expiry (
SETEX), refreshed on each request for a sliding timeout; DynamoDB with TTL is the serverless alternative (notes/dynamodb-guide.md§14); ALB sticky sessions (notes/ec2-mastery-guide.md§9) keep state on one instance and lose it when that instance goes away. - Leaderboards: sorted sets (
ZADD,ZINCRBY,ZREVRANGE … WITHSCORES); counters and rate limits:INCRplusEXPIRE. - Hot-key stampede (many clients miss the same key at once after it expires): add TTL jitter, let one caller rebuild the entry while others wait, or refresh popular keys before they expire.
- Caching a database through ElastiCache always needs application code; for DynamoDB reads with minimal code change, DAX is the managed write-through cache (
notes/dynamodb-guide.md§10).
Developer angle
Cache-aside reads plus write-through updates, with a jittered TTL:
import json
import os
import random
import redis # redis-py; the same client API works against Valkey
cache = redis.Redis(host=os.environ["CACHE_HOST"], port=6379, ssl=True,
decode_responses=True)
BASE_TTL = 300 # seconds
def get_product(product_id: str, db) -> dict:
key = f"product:{product_id}"
cached = cache.get(key)
if cached is not None: # hit
return json.loads(cached)
row = db.fetch_product(product_id) # miss: go to the database
if row is not None:
cache.set(key, json.dumps(row), ex=BASE_TTL + random.randint(0, 60))
return row
def update_price(product_id: str, price: float, db) -> None:
row = db.update_price(product_id, price) # the database stays the source of truth
cache.set(f"product:{product_id}", json.dumps(row), ex=BASE_TTL) # write-through
def save_session(session_id: str, data: dict) -> None:
cache.setex(f"session:{session_id}", 1800, json.dumps(data)) # 30-minute session
Let the cache evict any key, not only keys with a TTL (custom parameter group, node-based clusters):
aws elasticache modify-cache-parameter-group --cache-parameter-group-name catalog-params \
--parameter-name-values "ParameterName=maxmemory-policy,ParameterValue=allkeys-lru"
Traps
- Trap: "Lazy loading never serves stale data." → Reality: it does until the key expires or is invalidated.
- Trap: "Write-through alone fills a new node." → Reality: keys appear only when written again; keep lazy loading as the fallback.
- Trap: "TTLs are pointless with write-through." → Reality: AWS recommends TTLs with write-through too, to clear entries nobody reads (churn).
- Trap: "The default policy evicts any key when memory is full." → Reality:
volatile-lruevicts only keys with a TTL. - Trap: "Frequent evictions are fixed by a longer TTL." → Reality: longer TTLs keep more data in memory; scale up or out, or cache less.
- Trap: "Sticky sessions make the web tier stateless." → Reality: they pin users to one instance; a shared session store does.
- Trap: "Cache every query." → Reality: cache read-heavy, slowly changing data; volatile or must-be-exact data belongs in the database.
Practice questions
-
A product catalog service uses lazy loading with Amazon ElastiCache for Valkey and a 6-hour TTL. When merchants change a price in Amazon RDS, customers keep seeing the old price for hours. Prices must be correct right after an update, and the cache shouldn't fill with products nobody views. What should a developer do?
- A. Update or delete the cached entry in the code that writes a new price, and keep TTLs on all keys.
- B. Lower the TTL of every cached product from 6 hours to 1 second.
- C. Switch every table to write-through caching and remove the TTLs from all keys.
- D. Move the cache to a larger node type with more memory for products.
-
An application stores web sessions in a node-based Amazon ElastiCache for Valkey cluster without setting any TTL. Memory usage is at 100 %, and new logins fail with
OOM command not allowed when used memory > 'maxmemory'. The cluster uses the default parameter values. Which TWO actions fix the problem? (Select TWO.)- A. Write each session with an expiry, for example
SETEXwith a 30-minute timeout. - B. Add shards or move to a larger node type so that the active sessions fit in memory.
- C. Raise
reserved-memory-percentto 50. - D. Replace the cluster with Amazon ElastiCache for Memcached.
- E. Turn off Multi-AZ to free memory used by replicas.
- A. Write each session with an expiry, for example
Answers
- A. Writing or invalidating the key when the price changes keeps prices current, and TTLs still expire entries nobody reads. B hammers the database and still allows a second of staleness; C caches every table (churn) and keeps unread data forever; D doesn't fix staleness.
- A, B. The default
volatile-lrupolicy evicts only keys with a TTL, so sessions need expiries, and the remaining live sessions need enough memory. C reserves more memory for overhead and leaves less for data; D gives up replication without fixing the missing expiries; E doesn't free primary memory and removes failover.
Quick decision rules
RDS fundamentals, replicas and Multi-AZ (§1–§3)
- If you see storage that must grow automatically without downtime, think storage autoscaling (
--max-allocated-storageabove the allocated size). - If you see a large bulk load on an instance with autoscaling, think pre-size storage (4 modifications per 24 h, optimization waits).
- If you see
Too many connectionsfrom many short-lived clients, think RDS Proxy (or a connection pool) before a bigger instance. - If you see read-heavy reporting that slows the primary and tolerates seconds of lag, think read replica on its own endpoint.
- If you see "users don't see their own update", think read-after-write from the primary (replicas are asynchronous).
- If you see "automatic failover to another AZ" with no read requirement, think Multi-AZ DB instance (synchronous standby, 60–120 s).
- If you see automatic failover under a minute plus readable standbys on RDS for MySQL or PostgreSQL, think Multi-AZ DB cluster and its reader endpoint.
- If you see an application that can't reconnect for long after failover, think DNS caching (JVM TTL ≤ 60 s) and retry logic.
- If you see a Region-level disaster-recovery requirement, think cross-Region read replica (promote) or Aurora Global Database.
- If you see a major version upgrade with minimal downtime and no connection-string change, think blue/green deployment and switchover.
- If you see analytics that must use specific Aurora replicas, think custom endpoint with static members.
- If you see the wrong replica promoted after failover, think promotion tiers (0 = preferred, 15 = last).
- If you see read traffic that rises and falls on Aurora, think Aurora Auto Scaling on
RDSReaderAverageCPUUtilizationor connections. - If you see global low-latency reads and Region recovery in seconds, think Aurora Global Database (up to 10 secondary Regions).
- If you see an intermittent or idle-at-night Aurora workload, think Aurora Serverless v2 with
MinCapacity0 (auto-pause). - If you see an Aurora serverless cluster that never pauses, think open connections, RDS Proxy, replication or provisioned instances.
- If you see Lambda without VPC access running short SQL on Aurora, think RDS Data API with
secretArnandrds-data:ExecuteStatement. - If you see Data API timeouts on long statements, think the 45-second limit (
continueAfterTimeoutfor DDL) or a driver connection.
RDS Proxy, security and backups (§6–§8)
- If you see Lambda connection storms that must still be served, think RDS Proxy; if throttling is acceptable, think reserved concurrency.
- If you see high
DatabaseConnectionsCurrentlySessionPinned, think moveSETstatements intoInitQueryor a session pinning filter. - If you see "no secrets at all" between proxy and database, think end-to-end IAM (
DefaultAuthScheme IAM_AUTH). - If you see "encrypt an existing unencrypted database", think encrypted snapshot copy and restore, or a blue/green deployment with a target KMS key.
- If you see "no database passwords in code", think IAM database authentication (
rds-db:connecton thedbuserARN) or Secrets Manager. - If you see
AccessDeniedfor IAM database login, think wrong ARN (instance name instead ofDbiResourceId) orrds:instead ofrds-db:. - If you see clients that must not connect without TLS, think
rds.force_ssl = 1(PostgreSQL) orrequire_secure_transport = ON(MySQL). - If you see an accidental delete on Aurora MySQL with a backtrack window, think
backtrack-db-cluster; elsewhere think PITR into a new instance. - If you see "share an encrypted snapshot", think customer managed key plus key policy, then
modify-db-snapshot-attribute. - If you see a production-like test copy of Aurora needed fast and cheaply, think copy-on-write clone.
ElastiCache and MemoryDB (§9–§10)
- If you see sorted rankings, pub/sub, replicas or failover in a cache, think Valkey/Redis OSS, not Memcached.
- If you see the simplest multi-threaded object cache without persistence, think Memcached.
- If you see an unpredictable cache workload with no capacity planning, think ElastiCache Serverless (TLS always; Valkey/Redis OSS authenticate only through RBAC).
- If you see an in-memory store that must not lose acknowledged writes, think MemoryDB or ElastiCache for Valkey 9.0+ with synchronous durability.
- If you see stale cache entries after database updates, think write-through or invalidation plus TTL.
- If you see a cache filling with data nobody reads, think lazy loading plus TTL.
- If you see
OOM command not allowedwith keys that have no TTL, thinkvolatile-lrudefault: add TTLs, change the policy or scale. - If you see session state lost when an instance is replaced, think shared session store in ElastiCache or DynamoDB.
Changed vs older material
Learn the Current column; older practice material may still show the Course / older material may say value. Rows that you confirm during /ingest are added to notes/current-facts.md.
| Topic | Course / older material may say | Current (verified 2026-10-12) | Source |
|---|---|---|---|
| §1 · Storage autoscaling trigger | Grows storage when free space < 10 %, low space ≥ 5 min and a 6-hour wait after the last modification | Free space ≤ 10 %, low space ≥ 5 min, previous storage optimization finished and fewer than 4 storage modifications in the past 24 hours; increment = max(10 GiB, 10 %, predicted 7-hour growth) | AWS docs |
| §1 · Database load monitoring | Performance Insights dashboard | CloudWatch Database Insights; Performance Insights console experience end of life 2025-11-30 (API remains) | AWS docs |
| §3 · Multi-AZ and reads | Multi-AZ standbys never serve reads; not for scaling | Still true for a Multi-AZ DB instance; a Multi-AZ DB cluster (RDS for MySQL/PostgreSQL) has two readable standbys, a reader endpoint and failover typically under 35 s | AWS docs |
| §4 · Aurora replica lag | Replica lag under 10 ms | Usually much less than 100 ms | AWS docs |
| §4 · Aurora failover time | Instantaneous / under 30 seconds | With a replica: typically < 60 s, often < 30 s; without a replica: new writer typically < 10 min | AWS docs |
| §4 · Aurora maximum storage | Up to 128 TB, grows in 10 GB increments | 256 TiB on Aurora MySQL 3.10+ and Aurora PostgreSQL 15.13+/16.9+/17.5+ (128 TiB on earlier versions); grows automatically and shrinks when data is removed | AWS docs |
| §4 · Aurora Global Database size | Up to 5 secondary Regions | Up to 10 read-only secondary Regions, replication typically under 1 s, up to 16 readers per secondary | AWS docs |
| §5 · Aurora Serverless v2 capacity | 0.5–128 ACUs; only Serverless v1 pauses | 0–256 ACUs on current engine versions (256 since 2024-10-03; auto-pause at 0 ACU since 2024-11-20, SecondsUntilAutoPause 300–86,400 s) |
AWS docs |
| §5 · Aurora Serverless v1 | Recommended for intermittent workloads | End of life 2025-03-31; no new v1 clusters after 2025-01-08 | AWS docs |
| §5 · RDS Data API scope | Aurora Serverless v1 only | Aurora PostgreSQL and Aurora MySQL with provisioned or Serverless v2 instances (Aurora MySQL since 2024-09-26) | AWS docs |
| §6 · RDS Proxy to database authentication | Credentials must be stored in Secrets Manager | Since 2025-09-12 also end-to-end IAM (DefaultAuthScheme IAM_AUTH, no secrets; MySQL/MariaDB/PostgreSQL families) |
What's New |
| §7 · Encrypting an existing database | Only snapshot → encrypted copy → restore | That path, or a blue/green deployment whose green environment uses a target KMS key (TargetKmsKeyId); Aurora can also restore an unencrypted snapshot into an encrypted cluster |
AWS docs |
| §7 · Aurora encryption default | Unencrypted unless chosen at launch | New Aurora clusters created on or after 2026-02-18 are encrypted by default with an AWS owned key | AWS docs |
| §7 · Default TLS certificate authority | rds-ca-2019 |
rds-ca-rsa2048-g1 (also rds-ca-rsa4096-g1, rds-ca-ecc384-g1); automatic server certificate rotation |
AWS docs |
| §7 · PostgreSQL TLS enforcement | rds.force_ssl off by default |
Default 1 (TLS required) on RDS for PostgreSQL 15+; 0 on 14 and earlier | AWS docs |
| §7 · IAM DB auth connection rate | Use only below 200 new connections per second | No rate ceiling documented; needs 300–1,000 MiB extra DB memory; use RDS Proxy for high connection rates | AWS docs |
| §9 · ElastiCache engines | Redis or Memcached | Valkey, Memcached and Redis OSS; Valkey since 2024-10-08 (serverless 33 % / node-based 20 % cheaper, zero-downtime upgrade); Valkey 9.1 is the newest engine version (release date ⚠️ unverified) | What's New |
| §9 · ElastiCache network access | Reachable only from inside the VPC | Serverless Valkey 9.0+ caches can use a public endpoint with IAM authentication and TLS 1.3 (2026-09-29); node-based clusters stay VPC-only | AWS docs |
| §9 · Redis persistence | Durability through AOF persistence | AOF (appendonly, appendfsync) not supported; use replicas and snapshots, or Valkey 9.0+ durability (sync/async Multi-AZ transactional log) |
AWS docs |
| §9 · MemoryDB name and engines | Amazon MemoryDB for Redis (Redis-compatible) | Amazon MemoryDB, compatible with Valkey (since 2024-10-08) and Redis OSS | AWS docs |
| §10 · TTL with write-through | A TTL isn't needed when you use write-through | Add a TTL to every write, write-through included, to limit cache churn | AWS docs |
Not confirmed in current AWS documentation (don't learn as facts): Aurora's "5x MySQL / 3x PostgreSQL" performance and "about 20 % more expensive than RDS" price claims, and MemoryDB's "over 160 million requests per second".