DEV Community

Tejas Shinkar
Tejas Shinkar

Posted on Edited on

AWS RDS & ElastiCache — Managed Databases, Multi-AZ Failover & In-Memory Caching

Part of my AWS learning journey — exploring AWS hands-on and building a deeper understanding of Cloud & DevOps. This session moves from networking into the data layer — how AWS manages databases for you, and how caching keeps applications fast.


📋 Topics Covered

# Topic Type
1 Why Separate Compute from Database Concept
2 Structured vs Semi-Structured vs Unstructured Data Concept + Interview
3 What RDS Actually Is Under the Hood Concept + Interview
4 RDS Deployment Options — Single-AZ vs Multi-AZ Instance vs Multi-AZ Cluster Concept + Cert
5 Self-Managed DB vs RDS — What AWS Automates Concept + Interview
6 RDS DB Authentication Concept + Cert
7 RDS Read Replicas Concept + Interview
8 RDS Custom Concept + Cert
9 Multi-AZ Failover — Step by Step Concept + Cert
10 Why RDS Uses a DNS Endpoint, Not an IP Interview
11 RDS DB Security Concept + DevOps
12 RDS Proxy Concept + DevOps
13 Amazon Aurora — Cluster, Storage, Endpoints, Serverless, Global Concept + Cert
14 Sharding — Horizontal Scaling Concept + Interview
15 Amazon ElastiCache Concept + Interview
16 Cache Patterns & Cache Invalidation Strategy Concept + DevOps
17 Redis vs Memcached Concept + Interview
18 Lab 1 — Launch an RDS Instance, Explore Every Configuration Option Lab
19 Lab 2 — Modify RDS from Single-AZ to Multi-AZ Lab
20 Lab 3 — Set Up ElastiCache for a DB Cluster Lab
21 Interview Questions Interview
22 Assignment Practice

Why Separate Compute from Database

An application server (EC2, Lambda) is built to process data quickly — run logic, transform data, respond to requests. A database is built to store data reliably — persist it, keep it searchable, keep it available to multiple clients at once, and survive restarts.

If you put both on the same machine, a crash takes down your entire system — your data and your processing logic disappear together. Keeping them separate means your application servers can scale up, scale down, or crash and restart, while your data stays safe and available on its own dedicated, purpose-built infrastructure.

The core principle: Compute is optimized for processing. A database is optimized for persistent, reliable, searchable, shared storage. Separating them lets each scale independently and lets your application survive server failures without losing data.


Structured vs Semi-Structured vs Unstructured Data

Not all data looks the same, and AWS has a different storage service optimized for each type.

Data Type Schema Example AWS Service
Structured Fixed schema — rows and columns defined upfront Customer table: id, name, email, order_date Amazon RDS (relational)
Semi-structured Flexible schema — fields can vary per record JSON, XML — a user profile with optional fields Amazon DynamoDB (NoSQL)
Unstructured No predefined format at all Images, videos, PDFs, log files Amazon S3

Why this distinction matters in real architecture: A retail app might use RDS for orders (structured, needs strong consistency), DynamoDB for a shopping cart (semi-structured, needs speed and flexibility), and S3 for product images (unstructured, needs cheap durable storage). Picking the right store for each data type is a core system design skill.


What RDS Actually Is Under the Hood

This mental model makes RDS click immediately: RDS is not a magical new thing — it's an EC2 instance with attached EBS storage, running a database engine, wrapped in an AWS-managed control plane.

Think of it this way: underneath, RDS is still a virtual machine with a disk, just like any EC2 setup you could build yourself. What AWS adds on top is the automation layer — automatic provisioning, backups, patching, monitoring, scaling, and failover — so you never have to SSH in and manage the database server yourself.

What you get with RDS that you'd have to build yourself with self-managed EC2:

Task Self-Managed on EC2 Amazon RDS
Install DB engine Manual Pre-configured, just choose the engine
OS/DB patching Manual, scheduled downtime Automated maintenance windows
Backups You script and schedule them Automated daily snapshots + point-in-time recovery
Failover You build and test it yourself Automatic (Multi-AZ)
Monitoring You set up CloudWatch agents Built-in metrics out of the box
Scaling storage Manual resize + downtime Can auto-scale storage

RDS Deployment Options

RDS offers three deployment models, and this is one of the most tested concepts in the SAA-C03 exam. The image from class (RDS Console's deployment screen) shows this exact choice.

Memory trick:

  • Single-AZ → One copy 🏠
  • Multi-AZ Instance → One primary + one standby 🏠🏠
  • Multi-AZ DB Cluster → One writer + multiple readers 🏠🏠🏠

Side-by-Side Comparison

Single-AZ Multi-AZ DB Instance Multi-AZ DB Cluster
Instances 1 2 (1 primary + 1 standby) 3 (1 writer + 2 readable standbys)
Uptime SLA 99.5% 99.95% 99.95%
Automatic failover ❌ No ✅ Yes ✅ Yes
Standby readable N/A ❌ No (standby is idle, failover-only) ✅ Yes (readers serve read traffic)
Read scaling ❌ No ❌ No ✅ Yes
Redundancy across AZs ❌ No ✅ Yes ✅ Yes
Use case Dev, test, non-critical workloads Production, HA required Production, HA + read-heavy workloads
Cost Lowest Medium (2x compute) Highest (3x compute)

Reading the deployment screenshot from class:

  • Multi-AZ DB Cluster (3 instances): Primary instance + SSD in AZ 1, two "Readable standby + SSD" instances in AZ 2 and AZ 3. There's a separate "Reader endpoint" that load-balances read queries across the standbys, while the "Write/read endpoint" always points to the primary.
  • Multi-AZ DB Instance (2 instances): Primary in AZ 1, a standby in AZ 2 that has no endpoint of its own — it exists purely as a failover target, not for serving traffic.
  • Single-AZ (1 instance): Just the primary, no redundancy at all. If AZ 1 has an issue, there's no automatic failover — you'd be restoring from backup.

🎯 Cert tip: The key differentiator that trips people up — in a Multi-AZ Instance deployment, the standby is NOT readable. You cannot send read queries to it; it exists purely for failover. Only a Multi-AZ DB Cluster gives you readable standbys that also help with read scaling.


Self-Managed DB vs RDS — What AWS Automates

On a self-managed database (say, PostgreSQL installed manually on an EC2 instance), a DBA is responsible for installing the database binaries, configuring database parameters (memory allocation, connection limits, query optimization settings), and managing how clients connect.

RDS automates all three of these:

Self-Managed Task RDS Equivalent
Manually install DB binaries Choose an engine (PostgreSQL, MySQL, etc.) — AWS manages the binary
Manually edit config files (postgresql.conf) Parameter Groups — a managed collection of engine settings you can tune without SSH access
Manage static connection strings, update on every failover DNS Endpoint — a stable hostname that AWS keeps pointed at the current primary

Parameter Groups deserve a specific callout — instead of editing a config file directly on the server, you modify settings through a Parameter Group in the RDS Console, and AWS applies them to the instance (sometimes requiring a reboot, depending on the parameter).


RDS DB Authentication

RDS supports three ways for a client to authenticate to the database:

Method How It Works Best For
Password authentication Standard master username/password set at creation, stored/rotated by you (or via Secrets Manager) Default choice for most workloads
IAM database authentication Clients generate a short-lived auth token using IAM credentials instead of a static password (supported on MySQL and PostgreSQL engines) Environments that want to avoid long-lived DB passwords entirely and centralize access control in IAM
Kerberos authentication Integrates with Microsoft Active Directory for centralized authentication Enterprises already running AD-based identity management

💡 Why IAM authentication matters: tokens are valid for 15 minutes and are generated on demand using the caller's IAM permissions — there's no static password sitting in an application config file to leak or rotate manually. It's a common production/security hardening step once the basic connection works.


RDS Read Replicas

A Read Replica is an additional, separately-connectable copy of a database used to offload read traffic from the primary — different from a Multi-AZ standby, which exists purely for failover.

How it works: Data is replicated asynchronously from the primary to one or more read replicas. Applications can send read-only queries directly to a replica's own endpoint, reducing load on the primary. Most engines support up to 5 read replicas; Aurora supports up to 15.

Read Replica vs Multi-AZ Standby — don't mix these up:

Multi-AZ Standby Read Replica
Purpose High availability / failover Read scaling
Replication Synchronous Asynchronous
Readable ❌ No (Instance) / ✅ Yes (Cluster) ✅ Yes, always
Automatic failover target ✅ Yes ❌ No (must be manually promoted)
Can span Regions ❌ No ✅ Yes (cross-Region replicas supported)

Because replication is asynchronous, a read replica can lag slightly behind the primary — an important detail if your application can't tolerate reading slightly stale data.

🎯 Cert tip: If a question mentions "read-heavy workload" and "reduce load on the primary," the answer is Read Replica. If it mentions "automatic failover" and "high availability," the answer is Multi-AZ.


RDS Custom

RDS Custom is a variant of RDS (available for Oracle and SQL Server) that gives you OS-level and database-level access, while still getting some of RDS's automation.

Normal RDS deliberately hides the underlying OS — you can't SSH in or install custom agents. RDS Custom removes that restriction: you get shell access to the underlying instance and can customize the database environment for legacy applications or third-party software that require specific configuration RDS wouldn't normally allow.

The trade-off: with more access comes less of AWS's fully-managed guarantee — some automation (like certain automated backups or patching behavior) is deprioritized in favor of giving you control. Use RDS Custom only when a workload specifically requires OS-level customization that standard RDS can't accommodate.


Multi-AZ Failover — Step by Step

This is the mechanism that makes Multi-AZ deployments valuable — understanding exactly what happens during a failure builds real confidence for both interviews and production incidents.

The failover sequence:
Primary Crash → Standby Promoted → DNS Endpoint Updated (TTL = 5 seconds) → Application Resolves New IP → Reconnect → Database Available

Total time: roughly 60–120 seconds

Breaking down each step:

  1. Primary Crash — the primary instance becomes unreachable (hardware failure, AZ outage, or a manual failover for maintenance)
  2. Standby Promoted — AWS automatically promotes the standby replica in the other AZ to become the new primary
  3. DNS Endpoint Updated — the RDS DNS endpoint's record is updated to point to the new primary's IP address, with a TTL (Time To Live) of about 5 seconds
  4. Application Resolves New IP — because the DNS TTL is so short, client applications quickly pick up the new IP on their next DNS lookup
  5. Reconnect — the application's connection pool reconnects using the newly resolved IP
  6. Database Available — normal operations resume

The entire process typically completes within 60 to 120 seconds — no manual intervention required.


Why RDS Uses a DNS Endpoint, Not an IP

This is a genuinely good interview question because it tests whether you understand why a design choice was made, not just what it is.

Q: Why does RDS use a DNS endpoint instead of exposing the database IP directly?

During a Multi-AZ failover, the database's IP address changes — the standby gets promoted and it has a different IP than the old primary. If applications connected using a hardcoded IP, every failover would require someone to manually update every application's configuration and restart it — completely defeating the purpose of "automatic" failover.

Instead, applications connect using a stable RDS DNS endpoint (something like mydb.abc123xyz.ap-south-1.rds.amazonaws.com) that never changes. Behind the scenes, AWS updates what that DNS name resolves to. With a TTL of about 5 seconds, client applications re-resolve the DNS quickly and reconnect to the new primary automatically — with zero configuration changes needed on the application side.

This is exactly the same principle used by Elastic IPs and Route 53 health checks elsewhere in AWS — decouple the stable identifier from the underlying resource so the underlying resource can change without breaking anything upstream.


RDS DB Security

Securing an RDS database is a layered exercise — network, data, and identity all need attention.

  • Encryption at rest: RDS storage (data, automated backups, snapshots, read replicas) can be encrypted using a KMS key. This must be enabled at creation time — you cannot encrypt an existing unencrypted instance in place; you'd need to snapshot, copy the snapshot with encryption enabled, then restore.
  • Encryption in transit: Client-to-database connections can be secured with SSL/TLS certificates, preventing traffic from being read in transit even inside the VPC.
  • Network access control: RDS instances should sit in private subnets with a Security Group that only allows the application tier's Security Group on the DB port — never 0.0.0.0/0.
  • IAM database authentication: removes long-lived static passwords in favor of short-lived IAM-generated tokens (see the Authentication section above).
  • Secrets Manager integration: RDS can integrate with AWS Secrets Manager to store and automatically rotate the master credentials, so passwords aren't hardcoded in application configuration.

💡 Production pattern: private subnet + tightly-scoped Security Group + encryption at rest and in transit + credentials in Secrets Manager (with rotation enabled) is the baseline most production RDS deployments should meet.


RDS Proxy

RDS Proxy is a fully managed, highly available database connection pooler that sits between your application and RDS/Aurora.

The problem it solves: applications — especially serverless ones like Lambda — can open far more database connections than the database can handle, since each Lambda invocation might open its own connection. This can exhaust the database's connection limit and degrade performance.

RDS Proxy pools and multiplexes connections, so many application-side connections can share a smaller number of actual database connections. It also improves failover behavior — because RDS Proxy maintains the connection pool itself, applications keep their connection to the proxy open during a failover, and the proxy handles reconnecting to the newly promoted primary transparently, rather than every application instance needing to re-resolve DNS and reconnect individually.

RDS Proxy also supports IAM authentication, adding another option for removing static credentials from application code.

🎯 Cert tip: "Lambda + RDS + connection exhaustion" in a scenario question points straight at RDS Proxy.


Amazon Aurora

Amazon Aurora is AWS's own cloud-native relational database, compatible with MySQL and PostgreSQL (meaning your existing MySQL/PostgreSQL drivers and tools work without changes) but built with fundamentally different internal architecture for much higher performance.

What makes Aurora different from standard RDS engines:

Feature Standard RDS (MySQL/PostgreSQL) Aurora
Compute + Storage Coupled together Separated — storage scales independently
Replication You configure it Automatic, across 3 AZs, 6 copies of data
Storage auto-scaling Manual/limited Automatic, up to 128 TB
Failover speed ~60-120 seconds Faster (typically under 30 seconds)
Performance Baseline Significantly higher throughput
Cost Lower Higher (premium for the performance)

The "separates compute from storage" concept, explained simply: In a standard database, if you need more storage, you often need to resize the whole instance. In Aurora, the storage layer is a separate, distributed system that grows automatically as your data grows — the compute instance (which runs the actual query engine) can scale independently. This is why Aurora can offer both faster failover (the storage layer already has 6 copies ready) and larger scale (storage isn't tied to a single disk).

🎯 Cert tip: When a scenario mentions "MySQL-compatible," "PostgreSQL-compatible," "high performance," and "automatic storage scaling" together, the answer is almost always Aurora, not standard RDS.

Aurora Cluster Storage — Standard vs I/O-Optimized

Aurora clusters can be configured with one of two storage billing models:

Aurora Standard Aurora I/O-Optimized
Billing Storage + I/O operations billed separately Higher storage price, but no separate I/O charges
Best for Workloads with low/predictable I/O I/O-intensive or unpredictable workloads (heavy read/write apps)
Cost behavior Can spike if I/O volume is high or unpredictable Flat, predictable cost regardless of I/O volume

💡 If your workload does a lot of reads/writes and I/O charges are consistently a large share of the bill, I/O-Optimized usually works out cheaper and more predictable than Standard.

Aurora Custom Endpoints

Beyond the default cluster (writer) endpoint and reader endpoint, Aurora lets you define custom endpoints — a named endpoint pointing at a specific subset of instances in the cluster.

Example use case: route analytics/reporting queries to a specific set of replica instances (so heavy reporting queries don't compete with regular application read traffic), by creating a custom endpoint that only includes those instances.

Aurora Serverless

Aurora Serverless (v2) automatically scales database capacity up and down based on actual load, measured in Aurora Capacity Units (ACUs), instead of requiring you to provision a fixed instance size.

Best for: unpredictable or intermittent workloads — dev/test environments, new applications with unknown traffic patterns, or workloads with large usage spikes — where you'd otherwise be paying for a fixed instance sized for peak load 24/7.

Aurora Global Database

Aurora Global Database replicates an Aurora cluster across multiple AWS Regions, with typical replication lag under 1 second, using dedicated infrastructure separate from normal read-replica replication.

Best for: globally distributed applications that need low-latency local reads in multiple Regions, and disaster recovery scenarios — a secondary Region can be promoted to full read/write in around a minute if the primary Region has an outage.


Sharding — Horizontal Scaling for Databases

As a database grows, at some point one server (even a very large one) can't handle the write load or storage anymore. Sharding is the technique for scaling out — instead of one giant database, you split it into multiple smaller databases called shards, each holding a portion of the data.

How it works: A large database is partitioned into multiple smaller databases (shards) based on some key — for example, splitting users A-M into Shard 1 and users N-Z into Shard 2. Each shard stores only its subset of the data. The application (or a routing layer) determines which shard to query based on the data being requested, so both storage and write load get distributed across multiple database servers instead of one.

Why this matters: Vertical scaling (bigger instance) has a ceiling — eventually you run out of bigger instance types. Sharding is how systems scale writes and storage beyond what any single database server could handle, at the cost of added application complexity (your app needs to know which shard to query).

💡 Where this connects: This is conceptually the same "horizontal vs vertical scaling" idea from the ELB/ASG session — just applied to databases instead of compute. Vertical = bigger box. Horizontal (sharding) = more boxes, each handling a slice of the problem.


Amazon ElastiCache

Even a well-tuned database has a limit to how many reads it can serve per second, and every query — even a fast one — has some latency. ElastiCache is AWS's fully managed in-memory caching service — it stores frequently accessed data in RAM, which is dramatically faster than querying a database on disk.

How caching works in an application:

Application needs data → checks the cache first → if the data is there (cache hit), return it instantly from RAM → if the data isn't there (cache miss), query the database, get the result, store it in the cache for next time, then return it to the caller.

This means the first request for a piece of data is a normal database query, but every subsequent request for the same data is served from memory — orders of magnitude faster, and it takes load off the database entirely.

Three Caching Engines

Engine Persistence Replication Status
Valkey ✅ Yes ✅ Yes Open-source fork of Redis (community-driven, actively used going forward)
Redis OSS ✅ Yes ✅ Yes Long-standing standard, still widely used
Memcached ❌ No ❌ No Simpler, but largely fallen out of favor — no persistence or replication means data loss on restart

💡 Why Valkey exists: After a licensing change to Redis, the open-source community forked the last fully open-source version of Redis into a new project called Valkey — it's Linux Foundation-backed and functionally very similar to Redis. AWS supports it as a first-class ElastiCache engine going forward.


Cache Patterns & Cache Invalidation Strategy

Knowing that caching works is only half the picture — knowing when to write to the cache and when to remove stale data is what makes a cache reliable in production.

Caching Patterns

Pattern How It Works Trade-off
Lazy Loading (Cache-Aside) App checks cache first; on a miss, reads from the DB and writes the result into the cache Only requested data ever gets cached (efficient), but the first request for any item always pays a cache-miss penalty, and data can go stale if not invalidated
Write-Through Every write to the database is also immediately written to the cache Cache is always fresh for written data, but adds latency to every write, and can fill the cache with data that's never actually read

Most real systems combine both: write-through for hot, frequently-read data that changes via known write paths, and lazy loading for everything else.

Cache Invalidation Strategies

Strategy How It Works Risk
TTL expiration Every cached item expires automatically after a set time Simple, but the app can serve stale data for up to the full TTL window
Write-through update Update the cache value at the same time the DB is updated Cache stays fresh immediately, but adds complexity/latency to every write path
Delete-on-write (explicit invalidation) On a DB write, delete the corresponding cache key instead of updating it — the next read does a normal lazy-load and repopulates the cache with fresh data Generally preferred over updating the cache directly, because it avoids race conditions where a slow write updates the cache with data that's already stale by the time it lands

🎯 Cert/interview tip: "Delete, don't update" is the safer default for cache invalidation — updating the cache directly on write can lose a race with another concurrent write and leave the cache holding outdated data.


Redis vs Memcached

Both are in-memory data stores, but they solve different problems.

Feature Redis (OSS / Valkey) Memcached
Data structures Strings, lists, sets, sorted sets, hashes, streams Simple key-value strings only
Persistence ✅ Yes (can save to disk) ❌ No — data lost on restart
Replication ✅ Yes (primary/replica) ❌ No
Multi-AZ / HA ✅ Yes ❌ No
Transactions ✅ Yes ❌ No
Pub/Sub messaging ✅ Yes ❌ No
Multi-threading Mostly single-threaded (some ops multi-threaded) Multi-threaded
Typical use case Anything needing durability, complex data, or HA Very simple, disposable caching where raw throughput matters more than durability

Memcached is essentially legacy at this point — no persistence means a restart wipes your cache entirely, and no replication means no high availability. Almost all new projects choose Redis OSS or Valkey, reserving Memcached for cases needing pure simplicity and multi-threaded throughput with no durability requirement at all.


🧪 Lab 1 — Launch an RDS Instance, Explore Every Configuration Option

Objective

Launch a real RDS instance while deliberately stepping through every configuration section in the console — not just the defaults — to understand what each option actually controls.

Steps

Engine options:

RDS Console → Databases → Create database → Choose a database creation method: Standard create (to see every option, instead of Easy create) → Engine type: PostgreSQL (or MySQL) → note the available engine versions

Templates:

Choose a template: Production, Dev/Test, or Free tier → compare how selecting each template changes the defaults further down the page (Production defaults to Multi-AZ, Dev/Test does not)

Settings:

DB instance identifier: lab-rds-db
Master username: dbadmin
Credentials management: choose Self managed vs Managed in AWS Secrets Manager — select Secrets Manager to see automatic credential rotation as an option

Instance configuration:

DB instance class: Burstable classes (db.t3.micro) vs Standard/Memory-optimized classes — note the price/performance trade-off shown for each

Storage:

Storage type: General Purpose SSD (gp3) vs Provisioned IOPS (io1/io2) → Allocated storage → toggle Storage autoscaling and set a maximum threshold to see how it prevents manual resize operations later

Availability & durability:

Multi-AZ deployment: Do not create a standby vs Create a standby instance vs Create a Multi-AZ DB Cluster — this is the exact three-way choice from the deployment options concept above

Connectivity:

VPC: select your VPC → DB Subnet Group: select or create one restricted to private subnets → Public access: No → VPC security group: create/select one that only allows the DB port from your application's Security Group → Availability Zone: leave as no preference → Database port: leave default

Database authentication:

Choose Password authentication, then reopen the page and note that IAM database authentication is also available as a checkbox here

Monitoring:

Enable/disable Enhanced Monitoring and Performance Insights, and note the associated cost implications for a lab account

Additional configuration:

Initial database name → DB parameter group → Backup: enable automated backups and set a retention period → Backup window → Enable encryption and select a KMS key → Maintenance window → Enable deletion protection

Click Create database and wait for the status to become Available.

Verification

Once available, note down the endpoint from the RDS Console (Connectivity & security tab), and confirm it resolves:

nslookup <your-rds-endpoint>
Enter fullscreen mode Exit fullscreen mode

What to Observe

  • Which settings can be changed after creation vs which are locked in at creation time (e.g., encryption cannot be added retroactively).
  • How selecting the Production template pre-selects Multi-AZ and other HA-related defaults compared to Dev/Test.
  • That the DB Subnet Group step is really just "which private subnets across which AZs is this database allowed to live in."

🧪 Lab 2 — Modify RDS from Single-AZ to Multi-AZ

Objective

Take the Single-AZ instance from Lab 1 (or a fresh Single-AZ instance) and convert it into a Multi-AZ deployment, observing what AWS does behind the scenes.

Steps

RDS Console → Databases → select the instance → Modify

Scroll to Availability & durability → change Multi-AZ deployment from "Do not create a standby instance" to "Create a standby instance"

Scroll to the bottom → choose Apply immediately (for the lab, so you don't have to wait for the maintenance window) → Continue → review the summary → Modify DB instance

Verification

Databases → select the instance → Status will show Modifying, then later Available again

Configuration tab → Multi-AZ now shows Yes, and a second Availability Zone is listed as the standby's AZ

While the modification is in progress, note whether your application (or a simple connection test) experiences a brief interruption — this mirrors what happens during a real failover, since AWS is provisioning a new standby and enabling synchronous replication to it.

What to Observe

  • The instance identifier and endpoint do not change — only the underlying architecture behind that endpoint changes.
  • The modification takes a few minutes; a production system would typically schedule this during a maintenance window rather than applying immediately.
  • Cost roughly doubles once Multi-AZ is enabled, since you're now paying for a second instance.

🧪 Lab 3 — Set Up ElastiCache for a DB Cluster

Objective

Deploy an ElastiCache (Redis/Valkey) cluster alongside the RDS database, connect to it from an EC2 instance, and manually verify basic cache read/write behavior.

Steps

Create a subnet group:

ElastiCache Console → Subnet groups → Create subnet group → select the same VPC as your RDS instance and EC2 → select the private subnets

Create the cache cluster:

ElastiCache Console → Redis OSS caches (or Valkey caches) → Create → Deployment option: Design your own cache → Cluster mode: disabled (for a simple lab) → Engine version → Node type: smallest available (e.g., cache.t3.micro) → Number of replicas: 0 for the lab → Subnet group: the one created above → Security group: create/select one allowing inbound on port 6379 only from your EC2 instance's Security Group

Click Create and wait for status Available.

Connect from EC2:

On an EC2 instance in the same VPC:

sudo yum install -y gcc jemalloc-devel openssl-devel tcl
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
sudo cp src/redis-cli /usr/local/bin/
Enter fullscreen mode Exit fullscreen mode

Connect to the cluster's primary endpoint:

redis-cli -h <your-elasticache-primary-endpoint> -p 6379
Enter fullscreen mode Exit fullscreen mode

Verification

Inside the redis-cli prompt, manually test the cache-aside pattern:

SET user:1001 "Alice"
GET user:1001
TTL user:1001
EXPIRE user:1001 60
Enter fullscreen mode Exit fullscreen mode

Confirm the value returns correctly with GET, and that TTL/EXPIRE behave as expected (a positive value counting down, then -2 once the key expires).

What to Observe

  • The Security Group on the cache cluster only permits the EC2 instance's Security Group — never open port 6379 to 0.0.0.0/0.
  • This manual SET/GET test is standing in for what an application layer would do automatically: check the cache first, and only query RDS on a miss.
  • With Number of replicas set above 0 in a real deployment, you'd get a reader endpoint too — conceptually identical to RDS's own reader/writer endpoint split.

⚡ Quick Revision

Why Separate Compute & DB
Compute = optimized for processing. Database = optimized for persistent, reliable, shared storage. Separation lets each scale independently and survive failures.

Data Types
Structured (fixed schema) → RDS. Semi-structured (flexible schema, JSON/XML) → DynamoDB. Unstructured (no format) → S3.

What RDS Really Is
EC2 + EBS + DB engine + AWS-managed automation layer (provisioning, backups, patching, monitoring, scaling, failover).

Three Deployment Options

  • Single-AZ 🏠 → one instance, no failover, 99.5% SLA
  • Multi-AZ Instance 🏠🏠 → primary + non-readable standby, automatic failover, 99.95% SLA
  • Multi-AZ Cluster 🏠🏠🏠 → one writer + 2 readable standbys, failover + read scaling, 99.95% SLA

DB Authentication
Password (default) · IAM auth (short-lived tokens, no static password) · Kerberos (AD integration).

Read Replica vs Multi-AZ
Read Replica = async, read scaling, not an auto-failover target. Multi-AZ standby = sync, HA/failover target, readable only in Cluster mode.

RDS Custom
Gives OS/DB-level access (Oracle, SQL Server) for legacy/custom needs, at the cost of some managed-service automation.

Failover Flow
Primary Crash → Standby Promoted → DNS Updated (TTL 5s) → App Resolves New IP → Reconnect → Available. Total: 60-120 seconds.

Why DNS Endpoint, Not IP
IP changes on failover. DNS endpoint stays constant; AWS updates what it resolves to. Apps never need reconfiguration.

RDS Security
Encryption at rest (KMS, set at creation) + in transit (SSL/TLS) + private subnet & scoped Security Group + IAM auth + Secrets Manager rotation.

RDS Proxy
Managed connection pooler; fixes connection exhaustion (esp. from Lambda) and keeps app connections open across failover while it reconnects to the new primary behind the scenes.

Aurora
MySQL/PostgreSQL-compatible, but compute and storage are separated. 3 AZs, 6 copies of data automatically. Auto-scales storage to 128 TB. Faster failover, higher performance than standard RDS. Storage billing: Standard (pay per I/O) vs I/O-Optimized (flat, no separate I/O charge). Custom Endpoints route queries to a specific subset of instances. Serverless v2 auto-scales capacity (ACUs) for unpredictable workloads. Global Database replicates cross-Region with <1s lag for global reads + DR.

Sharding
Horizontal scaling for databases — split one large DB into multiple shards, each holding a subset of data, distributing storage and write load.

ElastiCache
In-memory caching. Cache hit = instant from RAM. Cache miss = query DB, store result in cache, return. Engines: Valkey (Redis fork, active), Redis OSS (standard), Memcached (legacy, no persistence/replication).

Cache Patterns & Invalidation
Lazy Loading (cache-aside, load on miss) vs Write-Through (write to cache on every DB write). Invalidate by TTL, write-through update, or — preferably — delete-on-write to avoid race conditions.

Redis vs Memcached
Redis: rich data structures, persistence, replication, HA, transactions, pub/sub. Memcached: simple key-value only, no persistence/replication, multi-threaded — largely legacy now.


💼 Interview Questions

Q1: Why does AWS keep compute and database storage separate instead of running everything on one server?
Compute is optimized for processing logic quickly, while databases are optimized for persistent, reliable, and shared storage. Keeping them separate allows application servers to scale independently, restart, or fail without losing data, since the database lives on its own dedicated, durable infrastructure.

Q2: What is the difference between a Multi-AZ DB Instance and a Multi-AZ DB Cluster?
A Multi-AZ DB Instance has one primary and one standby — the standby is not readable and exists purely for automatic failover. A Multi-AZ DB Cluster has one writer and two readable standbys across different AZs, providing both automatic failover and read scaling, since the standbys can serve read traffic through a separate reader endpoint.

Q3: Walk through what happens during an RDS Multi-AZ failover.
The primary instance becomes unavailable, so AWS automatically promotes the standby in another AZ to primary. The RDS DNS endpoint's record is updated to point to the new primary's IP, with a TTL of about 5 seconds. Applications re-resolve the DNS quickly and reconnect using the new IP — no manual configuration changes needed. The whole process typically takes 60 to 120 seconds.

Q4: Why does RDS use a DNS endpoint instead of a static IP address?
Because the underlying IP address changes during failover — the standby that gets promoted has a different IP than the old primary. If applications connected via a hardcoded IP, every failover would require manual reconfiguration. The DNS endpoint stays constant while AWS updates what it resolves to, with a short TTL so clients pick up the change within seconds automatically.

Q5: What is the difference between a Read Replica and a Multi-AZ standby?
A Read Replica is an asynchronously replicated, independently queryable copy used to offload read traffic — it is not an automatic failover target and must be manually promoted. A Multi-AZ standby is synchronously replicated specifically for high availability, and is automatically promoted during failover, but is only readable when using a Multi-AZ DB Cluster rather than a Multi-AZ DB Instance.

Q6: What makes Amazon Aurora different from standard RDS engines like MySQL or PostgreSQL on RDS?
Aurora separates compute from storage — the storage layer is a distributed system that automatically replicates across 3 AZs with 6 copies of data and scales up to 128 TB automatically. This architecture also enables faster failover and significantly higher performance compared to standard RDS engines, while remaining compatible with existing MySQL and PostgreSQL tooling.

Q7: What is sharding and when would you use it?
Sharding is a horizontal scaling technique where a large database is split into multiple smaller databases (shards), each storing a subset of the data. It's used when a single database instance can no longer handle the write load or storage requirements — even with vertical scaling — because it distributes both storage and write traffic across multiple servers.

Q8: How does ElastiCache improve application performance?
Applications check the cache before querying the database. On a cache hit, data is returned instantly from RAM, which is dramatically faster than a database query. On a cache miss, the application queries the database, then stores the result in the cache for future requests. This reduces database load and significantly improves response times for frequently accessed data.

Q9: Why is "delete-on-write" often preferred over "update-on-write" for cache invalidation?
Updating the cache directly on every database write can lose a race against another concurrent write — a slower write could overwrite the cache with data that's already stale by the time it lands. Deleting the cache key instead forces the next read to do a fresh lazy-load from the database, which is simpler and avoids that race condition, at the cost of one cache-miss penalty on the next read.

Q10: When would you use RDS Proxy?
RDS Proxy is used when an application — especially a serverless one like Lambda — opens far more database connections than the database can handle, risking connection exhaustion. RDS Proxy pools and multiplexes those connections into a smaller number of actual database connections, and it also keeps application connections open across a Multi-AZ failover, handling the reconnect to the new primary transparently.

Q11: Why is Memcached rarely chosen for new projects compared to Redis OSS or Valkey?
Memcached has no persistence (data is lost on restart) and no replication (no high availability). Redis OSS and Valkey both support persistence and replication, making them suitable for production caching layers where data durability and availability matter — which is why most new projects choose one of those two instead.


🔬 Assignment

1. Create a web server on EC2, host a simple application on it, connect it to the RDS database created in this session's lab, build a basic frontend, create a form that makes an entry into the database, and confirm the data actually persists by querying the database directly after submitting the form.

AWS Session 11 — RDS & ElastiCache | AWS Learning Series
Explored managed relational databases, Multi-AZ concepts, and caching strategies for faster, highly available applications. Next, diving into Aurora, ElastiCache Patterns & DynamoDB.

Top comments (0)