☰ All modules Tier 3 · RDS (with Aurora and ElastiCache) GuideCheat sheet ‹ ec2cloudfront ›
Contents
  1. How RDS (with Aurora and ElastiCache) appears on DVA-C02
  2. 1. RDS fundamentals and storage auto scaling
  3. 2. Read replicas
  4. 3. Multi AZ deployments and failover
  5. 4. Aurora storage endpoints and replicas
  6. 5. Aurora Serverless and the Data API
  7. 6. RDS Proxy
  8. 7. Encryption and IAM database authentication
  9. 8. Backups snapshots and restores
  10. 9. ElastiCache engines and MemoryDB
  11. 10. Caching strategies TTL and session stores
  12. Quick decision rules
  13. Changed vs older material

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. ⚠️ unverified marks 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 rds asks bank questions whose source_note links point at the ## N. headings below; /drill rds fires short recall prompts from notes/rds-cheat-sheet.md. Loop: read a section → answer its two practice questions before opening the answers → /explain the 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:

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

Exam facts

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

Practice questions

  1. A startup runs its mobile backend on Amazon RDS for MySQL. User growth is unpredictable, and last night the instance entered the storage-full state 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 FreeStorageSpace that invokes a Lambda function to call modify-db-instance with a larger --allocated-storage.
    • B. Modify the instance with a --max-allocated-storage value 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.
  2. 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
  1. B. A MaxAllocatedStorage value 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.
  2. 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

Exam facts

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

Practice questions

  1. A retailer's Amazon RDS for PostgreSQL instance serves an order-processing application. A new reporting tool runs long SELECT queries 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.
  2. 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 ReplicaLag metric with a 30-second threshold.
    • E. Promote the read replica so that it receives the writes directly.
Answers
  1. 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.
  2. 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

Exam facts

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

Practice questions

  1. 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.
  2. 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-failover every night to keep the standby warm.
    • E. Send read-only queries to the cluster's reader endpoint.
Answers
  1. 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.
  2. 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

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

Exam facts

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
}

Traps

Practice questions

  1. 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.
  2. 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
  1. 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.
  2. 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

Exam facts

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

Practice questions

  1. 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.
  2. A Lambda function that isn't attached to a VPC must run short INSERT and SELECT statements 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:ExecuteStatement on the cluster ARN and secretsmanager:GetSecretValue on 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
  1. 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).
  2. 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

Exam facts

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

Practice questions

  1. A serverless API uses AWS Lambda functions that query an Amazon RDS for MySQL instance. During traffic spikes the database returns Too many connections errors, 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.
  2. An RDS Proxy in front of an Aurora MySQL cluster reports a high DatabaseConnectionsCurrentlySessionPinned value, and connection reuse is poor. The application runs SET SESSION group_concat_max_len = 1000000 at the start of every request. Which TWO changes would improve multiplexing? (Select TWO.)

    • A. Raise MaxConnectionsPercent to 100.
    • B. Increase the idle client connection timeout to 8 hours.
    • C. Turn off RequireTLS on the proxy.
    • D. Move the SET statement into the proxy's initialization query and remove it from the application.
    • E. Add the EXCLUDE_VARIABLE_SETS session pinning filter after confirming that the application doesn't rely on session variables set outside the current transaction.
Answers
  1. 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.
  2. D, E. group_concat_max_len isn'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 variable SETs 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

Exam facts

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

Practice questions

  1. 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-instance with --storage-encrypted and --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-id set to the key, and restore a new instance from the copy.
    • D. Set require_secure_transport to ON in the instance's parameter group.
  2. 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_iam to the application's database user.
    • C. Attach a policy to the instance's IAM role that allows rds:Connect on the DB instance ARN.
    • D. Set rds.force_ssl to 0 so that the token can be sent without TLS.
    • E. Attach a policy to the instance's IAM role that allows rds-db:connect on arn:aws:rds-db:<region>:<account>:dbuser:<DbiResourceId>/<db-user>.
Answers
  1. 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.
  2. B, E. The database must accept IAM tokens for that user, and the role needs rds-db:connect on the dbuser resource. 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

Exam facts

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

Practice questions

  1. A developer accidentally ran a DELETE without a WHERE clause 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 DELETE and switch the application to the new cluster endpoint.
    • B. Run aws rds backtrack-db-cluster with a --backtrack-to time just before the DELETE.
    • 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.
  2. 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 all to its restore attribute.
    • B. Share the automated snapshot directly, because automated snapshots inherit the instance's sharing settings.
    • C. Copy the snapshot with --kms-key-id set 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-add and the partner's account ID.
    • E. Add the partner account to the key policy of the aws/rds key.
Answers
  1. 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.
  2. C, D. Snapshots encrypted with aws/rds can'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

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

Exam facts

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

Practice questions

  1. 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.
  2. 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 appendonly set to yes in 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
  1. 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.
  2. 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

Exam facts

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

Practice questions

  1. 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.
  2. 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 SETEX with 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-percent to 50.
    • D. Replace the cluster with Amazon ElastiCache for Memcached.
    • E. Turn off Multi-AZ to free memory used by replicas.
Answers
  1. 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.
  2. A, B. The default volatile-lru policy 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)

Aurora (§4–§5)

RDS Proxy, security and backups (§6–§8)

ElastiCache and MemoryDB (§9–§10)

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".