How to Migrate an RDS Database Between AWS Accounts
Moving your PostgreSQL or MySQL database to a new AWS account? Here's the complete snapshot-based migration process, including encrypted snapshots, KMS key sharing, and cleanup to stop charges.
Table of Contents
- The Cheapest RDS Instances
- Step 1: Check Snapshot Encryption
- Step 2: Create a Custom KMS Key
- Re-encrypt the Snapshot
- Step 3: Share the Snapshot
- Step 4: Copy Snapshot to New Account
- Step 5: Restore to New RDS Instance
- Step 6: Configure Security Group
- Step 7: Update Your App
- Step 8: Verify Data
- Step 9: Post-Restore Production Settings
- Step 10: Cleanup Old Account
- Snapshot Costs — Don't Ignore These
- Alternative: pg_dump
- Common Mistakes
- Bottom Line
How to Migrate an RDS Database Between AWS Accounts
Switching AWS accounts and need to bring your database along?
RDS snapshots make this straightforward — unless your snapshot is encrypted with the default AWS key. Then you need a few extra steps.
We recently migrated a 200GB PostgreSQL database between accounts. Here's exactly what we did.
The Cheapest RDS Instances
Before migrating, know what you're restoring to:
| Instance | vCPU | RAM | Monthly Cost | Best For |
|---|---|---|---|---|
| db.t4g.micro | 2 | 1GB | ~$12.10 | Staging, small apps |
| db.t4g.small | 2 | 2GB | ~$24.20 | Light production |
| db.t4g.medium | 2 | 4GB | ~$48.40 | Medium production |
db.t4g.micro is the cheapest. Graviton (ARM) instances are ~20% cheaper than Intel equivalents.
Do you even need RDS?
For staging, running PostgreSQL directly on your EC2 instance is free. Save RDS for production where you need automated backups, point-in-time recovery, and managed updates.
| Local PostgreSQL | RDS db.t4g.micro | |
|---|---|---|
| Cost | Free (on instance) | ~$14.40/mo |
| Automated backups | No | Yes |
| Point-in-time recovery | No | Yes |
| Multi-AZ failover | No | Optional |
| Best for | Staging/dev | Production |
Step 1: Check Snapshot Encryption
This determines your migration path.
Old account → RDS → Snapshots → select your snapshot → check the Encryption field.
If unencrypted: Skip to Step 3. Simple path.
If encrypted with default aws/rds key: You need extra steps. The default KMS key can't be shared across accounts. You must re-encrypt with a custom key first.
If encrypted with a custom KMS key: Add the new account ID to that key's policy, then skip to Step 3.
Most people hit the default key scenario. Here's how to handle it.
Step 2: Create a Custom KMS Key (Old Account)
KMS → Customer managed keys → Create key:
| Setting | Value |
|---|---|
| Key type | Symmetric |
| Key usage | Encrypt and decrypt |
| Key material origin | KMS (default) |
| Regionality | Single-Region key |
| Alias | rds-migration-key |
On the key policy page → Other AWS accounts → add your new account ID (12 digits).
To find your new account ID: log into the new account → click your name in the top right corner → Account ID is right there.
After creating the key, click into it and copy the Key ARN. You'll need it next.
Re-encrypt the Snapshot
Old account → RDS → Snapshots → select your snapshot → Actions → Copy snapshot:
| Setting | Value |
|---|---|
| Destination Region | Same region (you're just re-encrypting) |
| New identifier | your-snapshot-custom-key |
| Encryption | Enable |
| AWS KMS key | Select rds-migration-key (NOT the default aws/rds) |
If the custom key doesn't appear in the dropdown, paste the Key ARN.
Wait for status to become Available.
Step 3: Share the Snapshot
Old account → RDS → Snapshots:
- Select the re-encrypted snapshot (or original if unencrypted)
- Actions → Share snapshot
- Enter your new AWS account ID
- Save
The snapshot now appears in the new account under "Shared with me."
Step 4: Copy Snapshot to New Account
New account → RDS → Snapshots → Shared with me tab:
- Select the shared snapshot
- Actions → Copy snapshot
- Settings:
- Destination region: your target region (e.g.
us-east-2) - New identifier:
your-app-migration - Encryption: default
aws/rdskey is fine here (same account)
- Destination region: your target region (e.g.
- Copy
Wait for Available. Can take several minutes for large databases.
Step 5: Restore to New RDS Instance
New account → RDS → Snapshots → select the copy → Actions → Restore snapshot:
| Setting | Staging | Production |
|---|---|---|
| RDS Extended Support | Don't enable | Don't enable |
| Deployment | Single-AZ | Single-AZ (upgrade to Multi-AZ later) |
| Instance class | db.t4g.micro | db.t4g.micro |
| Storage | Keeps snapshot size (can't shrink) | Keeps snapshot size |
| Public access | No | Yes (temporarily for PgAdmin, remove later) |
| Database auth | Password | Password |
| Backup retention | 1 day | 7 days |
| Auto minor version upgrade | Enable | Enable |
| Deletion protection | Disable | Enable |
Storage note: If your snapshot is 200GB, the restored instance will have 200GB minimum. You can't shrink it below the snapshot size. To reduce storage cost, pg_dump the data after restore, create a fresh RDS with 20GB, and pg_restore into it.
Takes 5-10 minutes to become available.
Step 6: Configure Security Group
EC2 → Security Groups → find the RDS security group → Inbound rules:
| Type | Port | Source | Purpose |
|---|---|---|---|
| PostgreSQL | 5432 | Your EC2 security group | App access |
| PostgreSQL | 5432 | Your home IP/32 | PgAdmin (temporary) |
Find your IP at checkip.amazonaws.com.
Never open 5432 to 0.0.0.0/0. For production, remove the PgAdmin rule once you've verified the data.
Step 7: Update Your App
Get the endpoint: RDS → Databases → your instance → Connectivity & security → Endpoint.
Update .env:
DB_HOST=your-app.xxxxxxxxxxxx.us-east-2.rds.amazonaws.com
DB_PORT=5432
DB_NAME=your_database
DB_USER=postgres
DB_PASSWORD=your_password
DATABASE_URL=postgresql://postgres:your_password@your-app.xxxxxxxxxxxx.us-east-2.rds.amazonaws.com:5432/your_database
Restart:
docker-compose down && docker-compose up -d
Step 8: Verify Data
-- Check table count
SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';
-- Check row counts on important tables
SELECT 'users' as tbl, count(*) FROM users
UNION ALL
SELECT 'orders', count(*) FROM orders;
Compare with the old database. Numbers should match.
If you don't remember the master password, modify the RDS instance to reset it.
Step 9: Post-Restore Production Settings
After verifying, update production settings:
RDS → Databases → select instance → Modify:
| Setting | Update to |
|---|---|
| Multi-AZ | Enable (when budget allows, doubles cost) |
| Public access | No (remove PgAdmin access) |
| Copy tags to snapshots | Enable |
Some changes require brief downtime — apply during off-peak hours.
Step 10: Cleanup Old Account
This is critical. Forgotten resources keep charging you.
Delete in this order (after verifying new DB works):
| Resource | Where | Monthly cost if kept |
|---|---|---|
| RDS instance | RDS → Databases → Delete | Compute + storage |
| Manual snapshots | RDS → Snapshots → Delete each | $0.095/GB (~$19/mo per 200GB snapshot) |
| Migration snapshot copy | RDS → Snapshots → Delete | $0.095/GB |
| Custom KMS key | KMS → Schedule deletion (7-30 day wait) | $1/mo |
| S3 buckets | S3 → Empty → Delete | Storage charges |
| Elastic IPs | EC2 → Elastic IPs → Release | $3.60/mo if unattached |
| EC2 instances | EC2 → Terminate | Compute charges |
| NAT Gateways | VPC → NAT gateways → Delete | $32/mo |
| Load Balancers | EC2 → Load Balancers → Delete | Varies |
| EBS Volumes | EC2 → Volumes → Delete unattached | Storage charges |
Quick cost check: AWS Billing → Bills → see which services still have charges.
In the new account, also delete the migration snapshot (your-app-migration) after restore is verified. Your RDS automated backups handle ongoing protection.
Snapshot Costs — Don't Ignore These
RDS snapshots are charged at $0.095/GB/month:
| Snapshots | Size | Monthly Cost |
|---|---|---|
| 1 × 200GB | 200GB | ~$19 |
| 2 × 200GB | 400GB | ~$38 |
| 3 × 200GB (original + copy + migration) | 600GB | ~$57 |
Automated backups are free up to your DB instance storage size. Manual snapshots always cost money.
Alternative: pg_dump (No Snapshot Sharing)
If you can't share snapshots (permissions issues, deleted KMS keys, etc.), use pg_dump:
# Dump from old database
pg_dump -h old-rds-endpoint -U postgres -d your_db -F c -f backup.dump
# Restore to new database
pg_restore -h new-rds-endpoint -U postgres -d your_db -F c backup.dump
This also lets you restore into a smaller RDS instance (e.g. 20GB instead of 200GB).
Common Mistakes
Sharing default-encrypted snapshots. The aws/rds default KMS key can't be shared. Re-encrypt with a custom key first.
Forgetting to update the security group. Your app will timeout trying to connect. Always add your EC2 security group to the RDS inbound rules.
Opening port 5432 to the internet. Never set source to 0.0.0.0/0 for database ports.
Not cleaning up the old account. Snapshots, instances, and EBS volumes keep charging even when unused. Check your billing page.
Ignoring storage size. Restored instances inherit the snapshot's storage size. A 200GB snapshot means 200GB minimum storage (~$23/mo).
Bottom Line
RDS migration between accounts: re-encrypt → share → copy → restore. About 20 minutes of active work.
The tricky part is the KMS key dance for encrypted snapshots. Once you know the steps, it's straightforward.
And always clean up the old account. Those forgotten snapshots add up fast.
Need help with database migrations or AWS infrastructure?
We handle cloud migrations for teams across Nigeria and beyond.
📞 WhatsApp: +234 708 711 0468 📧 info@www.raspibtech.com 📍 Lagos Island
Related:
Need Help with Your Project?
Let's discuss how Raspib Technology can help transform your business
Related Articles
How to Migrate S3 Buckets Between AWS Accounts in 5 Minutes
Moving to a new AWS account? Here's how to migrate your S3 bucket data without losing a single file. Simple, fast, and free.
Read more →AWS Spot Instances: Run Your Staging Server for $2/Month
Stop paying $50+/month for staging servers. Here's how to set up a complete staging environment with AWS Spot Instances, auto-deploy via GitHub Actions, and free SSL.
Read more →Laravel 11: What Changed and Why You Should Care
Laravel 11 is out. Slimmer structure, better performance, and features that actually save time. Here's what matters.
Read more →