Amazon RDS (Relational Database Service)

Updated 5 min read index source
On this page11
  1. What you get vs self-managed Postgres on EC
  2. Storage and instance types
  3. Multi-AZ
  4. Read replicas
  5. Connection pooling: RDS Proxy
  6. Backups and PITR
  7. Performance Insights
  8. IAM authentication
  9. Cost optimizations
  10. Common gotchas
  11. Interview angle

Amazon RDS (Relational Database Service)

Managed relational databases on AWS — PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, plus the Aurora variants. AWS handles backups, patching, minor version upgrades, failover; you handle schema, indexes, queries, and pool sizing.

What you get vs self-managed Postgres on EC2

EC2 + manual RDS
OS patching you AWS
Minor version upgrades you AWS (with maintenance window)
Backups (snapshots, PITR) you write scripts built-in
Multi-AZ failover manual setup one checkbox
Read replicas manual streaming repl one click
Monitoring you install CloudWatch + Performance Insights
Cost EC2 + EBS premium over EC2

You give up: root access, custom extensions not on the supported list, kernel tuning, sometimes the latest minor version.

Storage and instance types

  • gp3 (general purpose SSD) — default; provisioned IOPS and throughput independent of size.
  • io1 / io2 — high IOPS workloads; expensive.
  • Aurora uses its own storage engine — see the Aurora doc.

Instance classes: db.r6g, db.m6i, db.t3 (burstable, avoid in prod). Right-sizing matters — memory is king for Postgres (shared_buffers, OS page cache).

Multi-AZ

A synchronous standby in another AZ. Failover takes 60-120s, automatic on instance failure. Standby is NOT a read replica — you cannot read from it. Failover triggers:

  • Primary becomes unreachable.
  • Primary’s AZ becomes unavailable.
  • Manual reboot with failover.
  • Instance class change (you can pre-resize standby to minimize downtime).
bash
aws rds modify-db-instance \
  --db-instance-identifier orders-db \
  --multi-az \
  --apply-immediately

Multi-AZ doubles your storage cost. Standby is hot but not visible.

Read replicas

Asynchronous logical replication. For Postgres, uses native streaming replication. Use cases:

  • Offload read-heavy queries (reporting dashboards, ETL).
  • Cross-region replicas for DR or latency.
  • Major-version upgrade: spin up replica on new version, switch.

Lag is real (usually < 1s, can spike). Read-after-write consistency is NOT guaranteed if you read from replica.

Promote a replica to standalone master in a DR scenario:

bash
aws rds promote-read-replica --db-instance-identifier orders-replica

Connection pooling: RDS Proxy

Postgres connections are expensive (a process per connection + memory). At Lambda scale or k8s with many pods, your DB drowns in connections before CPU is saturated.

RDS Proxy is managed pgbouncer-like pooling in front of RDS:

  • Multiplexes thousands of client connections to a smaller pool of DB connections.
  • Survives DB failovers transparently — clients reconnect to proxy, proxy reconnects to new primary.
  • Handles IAM auth or Secrets Manager creds.
  • Costs ~$0.015/h per vCPU of the underlying DB.

Gotcha: RDS Proxy pins connections (won’t multiplex) when you use prepared statements, session-level features (SET, advisory locks), or LISTEN/NOTIFY. With pinning, you lose the multiplexing benefit.

For app-side pooling: see Connection pooling.

Backups and PITR

  • Automated backups — daily snapshot + transaction logs for point-in-time recovery (PITR). Retention 1-35 days.
  • Manual snapshots — keep forever, can copy across regions.
  • PITR restores to any second in the retention window — creates a NEW DB instance, doesn’t modify the existing one.

PITR is slow (10s of minutes to hours depending on size). Plan recovery procedures accordingly — RTO ≠ RPO.

Performance Insights

The thing you’ll actually use in production. Visual breakdown of “what’s loading the DB right now”, grouped by query, user, host, wait event. Free for 7 days retention.

Top use case: finding the query causing CPU/IO spikes. pg_stat_statements extension shows aggregate; Performance Insights shows the time series.

IAM authentication

Instead of passwords, use short-lived IAM tokens to connect:

python
import boto3, psycopg
rds = boto3.client("rds")
token = rds.generate_db_auth_token(
    DBHostname="orders.cluster-xxx.us-east-1.rds.amazonaws.com",
    Port=5432, DBUsername="app",
)
conn = psycopg.connect(
    host="...", user="app", password=token,
    sslmode="require",
)

Token TTL is 15 min. Combine with IRSA (EKS) for keyless DB auth.

Throughput cap: IAM auth supports ~200 connections/sec — fine for human users, brittle for high-churn workloads. Use Secrets Manager + RDS Proxy at scale.

Cost optimizations

  • Reserved Instances — 1 or 3 year commit; ~30-60% off on-demand. Steady-state workloads win.
  • gp3 over io1 unless you need > 16k IOPS.
  • Stop dev/staging DBs after hours — RDS supports stopping for up to 7 days; storage still costs.
  • Right-size based on Performance Insights, not vibes.

Common gotchas

  • t3 burstable instances in prod. Run out of CPU credits, hard throttle, look fine in metrics until they don’t. Use only for dev.
  • Default max_connections scales with instance class. Going to a smaller instance drops your connection ceiling.
  • Major version upgrades require maintenance window + downtime; rehearse on a clone.
  • Aurora vs RDS confusion. Aurora is its own animal — different storage, different scaling, different connection model. Don’t assume RDS knowledge applies 1:1.
  • Multi-AZ standby isn’t a read replica. Many candidates fail this on interviews.
  • Free tier db.t3.micro runs out fast. Don’t build a product roadmap around it.

Interview angle 5

  • “RDS vs running Postgres on EC2 yourself?” — RDS gives managed backups, patching, failover, monitoring, IAM auth, and read replicas. You lose: root access, certain extensions, ability to run latest minor versions before AWS supports them. For 95% of teams, the trade is worth it.
  • “Multi-AZ standby vs read replica?” — Multi-AZ is synchronous failover within a region; standby is invisible (you cannot read from it). Read replica is asynchronous; you can read from it but expect lag and not read-after-write consistency.
  • “How do you handle connection pooling on RDS at Lambda scale?” — RDS Proxy. Many Lambdas each open connections → DB drowns. Proxy multiplexes thousands of client conns to a small DB pool, handles failover transparently. Watch for pinning when prepared statements / session state / LISTEN-NOTIFY are used.
  • “What’s PITR and how does it work?” — Point-In-Time Recovery; daily snapshot + transaction logs for the retention window. Restores create a new DB instance at the requested timestamp. RTO is slow (minutes to hours); plan accordingly.
  • “How do you do a major version upgrade with minimum downtime?” — provision a replica on the new version (cross-version replication where supported), let it catch up, switch traffic via a connection string change or DNS, promote, decommission old. Test thoroughly on a clone first.

Contents 0