Run PostgreSQL or MySQL without managing servers: launch an RDS instance, pick storage types, connect to it, add a standby for high availability, and protect data with automated backups and snapshots.
RDS (Relational Database Service) runs managed databases — PostgreSQL, MySQL, MariaDB, SQL Server, Oracle. Why managed: AWS handles patching, backups, and replication, so you get a database endpoint to connect to instead of a server to babysit. You still write normal SQL.
List the database engines and versions RDS can run
aws rds describe-db-engine-versions --engine postgres \
--query 'DBEngineVersions[].EngineVersion' \
--output text | tr '\t' '\n' | tail -5A DB instance is one running database server, sized like an EC2 instance (db.t3.micro, etc.). Why a subnet group: RDS needs to know which private subnets it may live in — you keep databases off the public internet. This command creates a real, billable PostgreSQL database.
Tell RDS which subnets it may use (use your PRIVATE subnets)
aws rds create-db-subnet-group \
--db-subnet-group-name my-db-subnets \
--db-subnet-group-description "private db subnets" \
--subnet-ids $PRIVATE_SUBNET $PRIVATE_SUBNET_BLaunch a small PostgreSQL instance
aws rds create-db-instance \
--db-instance-identifier my-postgres \
--engine postgres \
--db-instance-class db.t3.micro \
--master-username appadmin \
--master-user-password 'Ch00se-A-Strong-One!' \
--allocated-storage 20 \
--db-subnet-group-name my-db-subnets \
--vpc-security-group-ids $SG_IDRDS storage mirrors EBS: General Purpose (gp3) suits most apps; Provisioned IOPS (io2) buys guaranteed high throughput for demanding databases; Magnetic is legacy and slow. Why: a busy transactional database benefits from provisioned IOPS, while a small app is fine and cheaper on gp3.
Launch with Provisioned IOPS for a throughput-sensitive workload
aws rds create-db-instance \
--db-instance-identifier busy-db \
--engine postgres --db-instance-class db.m5.large \
--master-username appadmin --master-user-password 'Ch00se-A-Strong-One!' \
--allocated-storage 100 \
--storage-type io2 --iops 3000 \
--db-subnet-group-name my-db-subnetsOnce available, RDS gives you an "endpoint" (a hostname) and port. You connect with the same client you'd use locally (psql, mysql). Why the security group matters: the database only accepts connections the security group allows — open port 5432 from your app servers, not the world.
Get the connection endpoint and port
aws rds describe-db-instances --db-instance-identifier my-postgres \
--query 'DBInstances[0].Endpoint.[Address,Port]' --output textThen connect with a normal client (run from a server in the VPC): psql -h my-postgres.abc123.us-east-1.rds.amazonaws.com -U appadmin -d postgres
Multi-AZ keeps a synchronized standby copy in another Availability Zone. Why: if the primary fails, RDS flips to the standby automatically in a minute or two and your endpoint stays the same. It roughly doubles cost — use it for production, skip it for scratch databases.
Turn on Multi-AZ for an existing instance
aws rds modify-db-instance \
--db-instance-identifier my-postgres \
--multi-az \
--apply-immediatelyRDS takes automated daily backups and lets you restore to any second within the retention window ("point-in-time recovery"). You can also take manual snapshots that live until you delete them. Why both: automated backups cover "undo the last few days"; manual snapshots are deliberate save points before risky changes.
Set automated backups to keep 7 days of history
aws rds modify-db-instance --db-instance-identifier my-postgres \
--backup-retention-period 7 --apply-immediatelyTake a manual snapshot right now
aws rds create-db-snapshot \
--db-instance-identifier my-postgres \
--db-snapshot-identifier before-migrationRestore that snapshot into a brand-new instance
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier my-postgres-restored \
--db-snapshot-identifier before-migration