The managed database overhead that only makes sense when your team has an on-call rotation.

Every project reaches the same five-minute decision. You open the AWS console and RDS is right there, with a clean setup wizard, managed backups, and a checkbox that says “Multi-AZ deployment.” The voice in your head sounds responsible: use managed services, reduce operational burden, that is what professionals do.
So you click through and spin up a db.t3.micro: $0.018 an hour for compute, plus $2.30 for the minimum 20 GiB of gp3 storage, which puts you at roughly sixteen dollars per month before a single user shows up. Check the Multi-AZ box because the internet told you to, and that number roughly doubles.
My solo projects do not do this. They run MySQL on a $6 DigitalOcean Droplet. That is not laziness or cost-cutting. It is a deliberate call based on what RDS actually delivers and whether a solo team is structured to use it.
What You Are Buying When You Buy RDS
RDS is a packaging decision. MySQL is MySQL. What you are paying for is the infrastructure layer around it: automated backups with configurable retention, automated minor version patching during maintenance windows, and Multi-AZ standby replication for high availability.
The standby is the expensive part. With Multi-AZ enabled, RDS provisions a synchronous standby replica in a different Availability Zone. Every write committed on the primary is synchronously replicated to the standby before the transaction is acknowledged. This is not async replication where lag accumulates. It is blocking: the primary waits for the standby to confirm before returning success to your application.
The benefit of that synchronous standby is automatic failover. When the primary fails, RDS detects the failure, promotes the standby, and updates the DNS record for your database endpoint. AWS documents the failover time as 60 to 120 seconds for a standard Multi-AZ deployment with one standby. The database comes back without a human touching a console.
That sounds compelling. It is, in the right context. The problem is what “automatic failover” does not include.
The Model That Breaks
The mental model behind “just use RDS Multi-AZ” is that managed availability equals application availability. It does not.
When the primary fails and the standby gets promoted, the DNS endpoint updates. But your application has open database connections pointing at the old IP. PHP’s PDO does not detect a dead connection and reroute automatically. Laravel’s database connection pool does not know a failover occurred. Your app throws SQLSTATE[HY000]: General error: 2006 MySQL server has gone away until someone restarts the workers or the application code handles reconnection.
This is not a flaw in RDS. It is documented behaviour. After a failover, existing connections must be re-established. The point is simply that “automatic failover” means the database recovered automatically. Your application still has to notice and respond. You are not buying zero-downtime for your users. You are buying shorter database recovery time for your ops team.
The reconnection problem has a known fix in Laravel, but it requires deliberate implementation. In queue workers, DB::reconnect() re-establishes the database connection after detecting a lost one. For workers managed by Supervisor or Laravel Horizon, the standard approach is configuring autorestart on the Supervisor process group so a worker that crashes on a broken connection pool gets replaced automatically rather than left hanging. Neither of these behaviours is automatic. Neither is configured for you by choosing RDS. The database recovering on its own does not fix the application. That fix lives in your codebase, and it lives there whether MySQL runs on RDS or on a $6 Droplet.
The Mechanism: What You Are Actually Paying For
The actual value RDS Multi-AZ delivers is reduced recovery time without manual database intervention. Your primary goes down in the middle of the night. Without Multi-AZ, someone has to get paged, diagnose the failure, and either restart MySQL or manually promote a replica. With Multi-AZ, the database-side recovery is automatic in 60 to 120 seconds.
For this to matter to your users, two conditions have to be true simultaneously.
You have to know it happened. RDS publishes failover events to CloudWatch. For those events to wake someone up at three in the morning, you need CloudWatch alarms configured, SNS topics set up, and an alerting path that actually reaches a human. If you do not have this, the automatic failover fires silently. You find out when a user emails you the next morning.
Someone has to respond on the application side. Automatic database recovery handles the database. Your application is still broken until workers reconnect. If you run Laravel queue workers on EC2 or ECS, those workers need to restart or your application code needs a reconnection strategy. A connection pool that does not check for stale connections will keep throwing errors on the revived database instance. That response requires an engineer who knows what to do.
Both conditions have to hold at the same time. One without the other is not high availability — it is incomplete infrastructure. If neither condition holds (no alerting, no one on-call), Multi-AZ fires into a void. The database recovers in 90 seconds. Your application stays broken until business hours. You paid roughly $15 extra per month for a recovery that happened invisibly and made no difference to your users.
The Cost Comparison That Makes the Case
Here is what a minimal solo production setup costs on each platform, based on current pricing:
DigitalOcean Basic Droplet (1 GiB RAM, 1 vCPU)
- Monthly compute: $6.00
- Automated backups (20% weekly plan): $1.20
- Droplet Snapshots for DR (optional, $0.06/GiB): variable
- Total: $7 to $8 per month
AWS RDS db.t3.micro Single-AZ
- Monthly instance ($0.018/hr on-demand): ~$13.14
- Storage (20 GiB gp3, minimum): $2.30
- Backup storage above free tier: variable
- Total: ~$15 to $16 per month
AWS RDS db.t3.micro Multi-AZ
- Instance cost roughly doubles: ~$26
- Storage roughly doubles: ~$4.60
- Total: ~$30 to $31 per month
The Droplet is four times cheaper than Multi-AZ. You are spending the difference on automatic failover that requires application-level reconnection logic to actually protect users, and alerting infrastructure you likely have not built.
This is not an argument that DigitalOcean is always better than AWS. It is a specific argument about what shape of guarantee RDS Multi-AZ delivers and whether your project can act on it.
What the $6 Droplet Actually Looks Like
On a fresh 1 GiB Droplet with Ubuntu 22.04, MySQL 8.0 installs cleanly from the default package repo. The limiting factor at that size is RAM, not CPU. MySQL’s default innodb_buffer_pool_size is 128 MiB. On a 1 GiB machine, setting it to 512 MiB gives the InnoDB engine more room to cache frequently read pages and reduces disk I/O considerably. A 2 GiB Droplet lets you push that to 1 GiB and handle moderately sized datasets without swapping.
If you are running a Laravel application with typical CRUD traffic and a database under 10 GiB, a 1 GiB Droplet handles it without complaint. Heavy analytical queries or large JOINs across millions of rows will saturate that buffer pool, and at that point you want the $12 or $24 Droplet anyway. The point is not that a $6 machine handles everything. The point is that it handles far more than people expect before they need to move up.
Your Laravel database config points at the Droplet’s IP with an application-only MySQL user and firewall rules that allow connections from your app server only:
// config/database.php: connecting to self-managed MySQL on Droplet
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'your_app'),
'username' => env('DB_USERNAME', 'app_user'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
// PDO error mode: throw exceptions on connection failures
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
],
],Backups are a shell script and a cron job. The part where people say “that is risky” and I say: the risk of a bad backup strategy is a different problem from the risk of database failure. RDS automated backups do not protect you from dropping the wrong table with a bad migration. You need tested, verified backups regardless of whether your database is managed.
#!/usr/bin/env bash
# /opt/scripts/db-backup.sh: runs nightly via cron, uploads to DO Spaces
set -euo pipefail TIMESTAMP=$(date +%Y-%m-%d_%H%M)
BACKUP_FILE="/tmp/app_db_${TIMESTAMP}.sql.gz"
SPACES_BUCKET="your-backup-bucket" mysqldump \
--user="${DB_USER}" \
--password="${DB_PASS}" \
--single-transaction \
--routines \
--triggers \
"${DB_NAME}" | gzip > "${BACKUP_FILE}" # Upload to DigitalOcean Spaces (S3-compatible endpoint)
aws s3 cp "${BACKUP_FILE}" "s3://${SPACES_BUCKET}/backups/" \
--endpoint-url "https://sgp1.digitaloceanspaces.com" rm -f "${BACKUP_FILE}"
--single-transaction takes a consistent InnoDB snapshot without a global table lock. You get a clean backup with no downtime. The output goes to DigitalOcean Spaces, which is S3-compatible and costs $0.02 per GiB per month. If the Droplet goes away entirely, the backup is in object storage.
When RDS Is Actually Worth It
There are real scenarios where RDS earns its cost. Be honest about whether you are in one of them.
- Your team has a defined on-call rotation and SLA commitments. Someone will receive the CloudWatch alert at three in the morning and take action. Multi-AZ meaningfully reduces the work that person has to do.
- You have compliance requirements. SOC 2, HIPAA and similar frameworks often require managed services with documented audit trails and automated patching records. RDS satisfies these requirements with less custom tooling.
- Patch discipline is genuinely hard to maintain. RDS handles MySQL minor version upgrades automatically in maintenance windows; if nobody on your team owns the upgrade runbook, that automation removes a real operational risk.
- Scale has a ceiling on a single Droplet. When you need read replicas, RDS Proxy for connection pooling and cross-region failover, the RDS ecosystem starts paying for itself in operational simplicity.
None of these apply to a side project with three users and no SLA. At that scale you are paying for infrastructure designed for a different team size.
The Assertion, Restated
RDS Multi-AZ is not general-purpose database hosting. It is an incident response tool that shortens the database portion of an outage from “manual intervention required” to “automatic 60 to 120 second recovery.” Your application still disconnects. Your team still needs to know it happened and respond on the application side. The database just recovers without a human touching it.
A $6 Droplet delivers none of that. What it delivers: MySQL, your data, and a monthly bill that starts at six dollars. For a solo project with no SLA, no on-call rotation and no compliance requirements, that trade-off is not a compromise.
It is the right call.


