RDS — Managed Databases
Amazon Relational Database Service (RDS) manages database administration — provisioning, patching, backups, and failover — so you focus on schema design and queries. RDS supports PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, and Amazon Aurora.
Why RDS Over Self-Managed DB on EC2?
| Task | Self-Managed EC2 | RDS |
|---|---|---|
| OS/database patching | You | AWS (maintenance windows) |
| Automated backups | You configure | Daily snapshots, point-in-time recovery |
| Multi-AZ failover | You build | Automatic (~60 seconds) |
| Read scaling | Manual replication | Read replicas in clicks |
| Monitoring | Install agents | Enhanced Monitoring + Performance Insights |
Create a PostgreSQL Instance
aws rds create-db-instance \
--db-instance-identifier myapp-postgres \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 16.1 \
--master-username dbadmin \
--master-user-password 'ChangeMeInProduction!' \
--allocated-storage 20 \
--storage-type gp3 \
--vpc-security-group-ids sg-database \
--db-subnet-group-name my-db-subnet-group \
--backup-retention-period 7 \
--multi-az \
--storage-encrypted \
--tags Key=Environment,Value=production
Console: RDS → Create database → PostgreSQL → Free tier or Production template → Configure VPC, security group, and credentials.
Connect to RDS
RDS instances in private subnets are not publicly accessible (recommended):
# From EC2 in same VPC
psql -h myapp-postgres.xxxx.us-east-1.rds.amazonaws.com \
-U dbadmin -d postgres
# Connection string for applications
DATABASE_URL=postgresql://dbadmin:[email protected]:5432/myapp
Use Secrets Manager to rotate credentials automatically instead of hardcoding passwords.
Engine Comparison
| Engine | Best For | RDS Feature Notes |
|---|---|---|
| PostgreSQL | Modern apps, JSON, extensions | Most popular open-source choice |
| MySQL/MariaDB | WordPress, legacy LAMP | Wide compatibility |
| Aurora PostgreSQL/MySQL | High throughput, auto-scaling storage | Up to 15 read replicas, serverless option |
| SQL Server | .NET enterprise apps | License included or BYOL |
| Oracle | Enterprise Oracle workloads | BYOL required |
Multi-AZ vs Read Replicas
| Feature | Multi-AZ | Read Replica |
|---|---|---|
| Purpose | High availability | Read scaling |
| Standby | Synchronous, automatic failover | Asynchronous, manual promotion |
| Endpoint | Same writer endpoint | Separate read endpoint |
| Use case | Production HA | Analytics, reporting queries |
# Create read replica
aws rds create-db-instance-read-replica \
--db-instance-identifier myapp-postgres-replica \
--source-db-instance-identifier myapp-postgres \
--db-instance-class db.t3.micro
Backups and Recovery
RDS performs automated daily snapshots and maintains transaction logs for point-in-time recovery (PITR):
# Manual snapshot
aws rds create-db-snapshot \
--db-instance-identifier myapp-postgres \
--db-snapshot-identifier myapp-postgres-manual-2024-06-13
# Restore to point in time
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier myapp-postgres \
--target-db-instance-identifier myapp-postgres-restored \
--restore-time 2024-06-13T10:30:00Z
Set backup-retention-period to 7–35 days based on compliance requirements.
Parameter Groups
Tune database settings without editing config files directly:
aws rds create-db-parameter-group \
--db-parameter-group-name postgres16-custom \
--db-parameter-group-family postgres16 \
--description "Custom PostgreSQL 16 parameters"
aws rds modify-db-parameter-group \
--db-parameter-group-name postgres16-custom \
--parameters "ParameterName=max_connections,ParameterValue=200,ApplyMethod=pending-reboot"
aws rds modify-db-instance \
--db-instance-identifier myapp-postgres \
--db-parameter-group-name postgres16-custom \
--apply-immediately
Common tuning parameters:
- PostgreSQL:
shared_buffers,work_mem,max_connections - MySQL:
innodb_buffer_pool_size,max_connections
Performance Insights and Monitoring
# Enable Performance Insights (free tier: 7 days retention)
aws rds modify-db-instance \
--db-instance-identifier myapp-postgres \
--enable-performance-insights \
--performance-insights-retention-period 7
Key CloudWatch metrics:
CPUUtilization— alert > 80%FreeableMemory— alert < 256 MBDatabaseConnections— compare tomax_connectionsReadLatency/WriteLatency— alert on spikes
Security
# Security group — allow only app tier
aws ec2 authorize-security-group-ingress \
--group-id sg-database \
--protocol tcp --port 5432 \
--source-group sg-app-servers
# Encryption at rest (enable at creation — cannot enable on existing unencrypted)
# Encryption in transit — require SSL in parameter group
# rds.force_ssl = 1 (PostgreSQL)
Store credentials in AWS Secrets Manager:
aws secretsmanager create-secret \
--name prod/myapp/database \
--secret-string '{"username":"dbadmin","password":"...","host":"myapp-postgres.xxxx.rds.amazonaws.com","port":5432,"dbname":"myapp"}'
Real-World Scenario: E-Commerce Database
| Component | Configuration |
|---|---|
| Primary | db.r6g.large, Multi-AZ, PostgreSQL 16 |
| Read replica | 1× db.r6g.large for reporting dashboards |
| Backups | 14-day retention, cross-region copy to us-west-2 |
| Subnet | Private subnets in 2 AZs via DB subnet group |
| Access | App servers via SG; admins via bastion + SSM |
| Secrets | Secrets Manager with 30-day rotation |
Aurora vs Standard RDS
| Feature | RDS PostgreSQL | Aurora PostgreSQL |
|---|---|---|
| Storage | Fixed allocation, up to 64 TiB | Auto-scales up to 128 TiB |
| Replicas | Up to 5 | Up to 15 |
| Failover | 60–120 seconds | ~30 seconds |
| Cost | Lower for small workloads | Better $/IOP at scale |
| Serverless | No | Aurora Serverless v2 |
Common Mistakes
- Publicly accessible RDS — keep in private subnets
- db.t3.micro in production — insufficient CPU and connections under load
- No Multi-AZ for production — single AZ failure = downtime
- Default parameter group — tune for your workload
- Running migrations without snapshots — always snapshot before schema changes
- Ignoring connection pooling — use RDS Proxy or PgBouncer for serverless/Lambda
Troubleshooting
| Issue | Diagnosis | Fix |
|---|---|---|
| Connection timeout | SG, NACL, wrong subnet | Verify SG allows app SG on DB port |
too many connections |
App leaking connections | Enable RDS Proxy; tune pool size |
| High CPU | Missing indexes, slow queries | Performance Insights → top SQL |
| Storage full | No autoscaling | Enable storage autoscaling (max threshold) |
| Failover took longer | Large buffer cache flush | Expected; test failover in maintenance window |
Best Practices
- Deploy in private subnets with Multi-AZ for production
- Use gp3 storage with provisioned IOPS for predictable performance
- Enable Enhanced Monitoring (1-second granularity)
- Automate credential rotation with Secrets Manager
- Use RDS Proxy for Lambda and connection-heavy apps
- Test restore procedures quarterly — backups you can’t restore are worthless
- Tag instances for cost allocation
Next: VPC — Networking.