Aurora vs Standard RDS
Both are managed relational databases. The difference:
Standard RDS: Runs vanilla MySQL, PostgreSQL, MariaDB, Oracle, or SQL Server on managed EC2 instances. Same engine you'd run on-prem, just with automated backups, patching, and failover.
Aurora: AWS's re-engineered storage layer under MySQL or PostgreSQL compatibility. Same SQL, same drivers, but:
- 5x throughput of standard MySQL, 3x of PostgreSQL (AWS's claim; real-world varies)
- Storage auto-scales (10GB to 128TB, no pre-provisioning)
- 6 copies of data across 3 AZs automatically
- Faster failover (~30 seconds vs 1-2 minutes for RDS)
- More expensive per-hour, but often cheaper overall due to storage efficiency
Rule of thumb: Use Aurora for production workloads. Use standard RDS for dev/test (cheaper minimum) or when you need Oracle/SQL Server.
Aurora Serverless v2
Scales compute capacity automatically based on demand. No instance size to choose. You set min and max ACUs (Aurora Capacity Units):
- Minimum: 0.5 ACU (~1GB RAM)
- Maximum: up to 256 ACUs
- Scales in 0.5 ACU increments, in seconds
Good for:
- Dev/staging environments (scales to minimum when idle)
- SaaS applications where tenant activity is unpredictable
- Workloads with burst patterns (overnight batch processing, business-hours traffic)
Provisioned instances are cheaper when:
- Traffic is steady and predictable
- You can right-size the instance accurately
- You're using Reserved Instances or Savings Plans
Cost comparison
A db.r6g.large (provisioned) running 24/7: ~$140/month Aurora Serverless v2 at equivalent capacity sustained: ~$175/month
But if that serverless instance spends 12 hours/day at minimum (nights/weekends), it costs ~$100/month. Variable workloads save money.
When to Use Relational vs DynamoDB
| Relational (Aurora/RDS) | DynamoDB | |
|---|---|---|
| Query flexibility | Ad-hoc queries, joins, aggregations | Predefined access patterns only |
| Schema | Rigid schema, migrations required | Flexible (but key design is fixed) |
| Scaling | Vertical + read replicas | Horizontal (unlimited) |
| Cost model | Instance-hours (always on) | Per-request or provisioned capacity |
| Idle cost | $50-500+/month minimum | $0 (on-demand) |
| Transactions | Multi-table ACID | Limited (single-partition preferred) |
| Best for | Complex queries, reporting, small-medium scale | High-throughput, known access patterns, serverless |
Choose relational when: You need joins, complex queries, ad-hoc reporting, or your team thinks in SQL and the workload doesn't need DynamoDB's scale.
Choose DynamoDB when: Access patterns are known, throughput is high, you want serverless scaling, or you need single-digit millisecond reads at any scale.
Read Replicas
Aurora supports up to 15 read replicas. Standard RDS supports up to 5.
When to use read replicas
- Read-heavy workloads (80%+ reads). Offload reads to replicas
- Reporting queries that would slow the writer
- Geographic distribution (cross-region replicas)
Reader endpoint
Aurora provides a reader endpoint that load-balances across all replicas. Your application uses two connection strings:
- Writer endpoint β for INSERT, UPDATE, DELETE
- Reader endpoint β for SELECT queries
RDS Proxy
Connection pooling as a managed service. Sits between your application and the database, pooling and multiplexing connections.
Critical for Lambda: Each Lambda invocation opens its own connection. At 100 concurrent invocations = 100 connections. At 1000 = database connection limit exceeded. RDS Proxy pools these efficiently.
Also useful for:
- ECS services with many tasks
- Applications with frequent connect/disconnect cycles
- Reducing failover time (proxy handles reconnection transparently)
Cost: 20% premium on top of your database cost. Worth it for Lambda workloads; evaluate for container workloads.
Multi-AZ vs Read Replicas
These solve different problems:
Multi-AZ (High availability):
- Synchronous replica in a different AZ
- Automatic failover if primary fails (~30s Aurora, ~60s RDS)
- Standby is not readable. It's only for failover
- Enable for all production databases
Read Replicas (Scalability):
- Asynchronous replication
- Readable. Use for read traffic
- Can be promoted to standalone if needed
- Minor replication lag (usually <100ms for Aurora)
CDK Example
import { DatabaseCluster, DatabaseClusterEngine, AuroraPostgresEngineVersion,
ClusterInstance, ServerlessV2ClusterInstanceProps } from 'aws-cdk-lib/aws-rds';
const cluster = new DatabaseCluster(this, 'Database', {
engine: DatabaseClusterEngine.auroraPostgres({
version: AuroraPostgresEngineVersion.VER_16_4,
}),
vpc,
vpcSubnets: { subnetType: SubnetType.PRIVATE_ISOLATED },
serverlessV2MinCapacity: 0.5,
serverlessV2MaxCapacity: 8,
writer: ClusterInstance.serverlessV2('writer'),
readers: [
ClusterInstance.serverlessV2('reader', { scaleWithWriter: true }),
],
defaultDatabaseName: 'myapp',
deletionProtection: true,
storageEncrypted: true,
iamAuthentication: true,
});
// RDS Proxy for Lambda access
const proxy = cluster.addProxy('Proxy', {
vpc,
secrets: [cluster.secret!],
iamAuth: true,
requireTLS: true,
});
proxy.grantConnect(lambdaFunction, 'app_user');
Cost Optimization Tips
- Use Serverless v2 for dev/staging. Scales to minimum when idle. No paying for a db.r6g.xlarge sitting at 2% CPU overnight.
- Right-size production. Most RDS instances are over-provisioned. Check Compute Optimizer recommendations.
- Reserved Instances or Savings Plans for steady-state production databases. 30-60% savings.
- Aurora I/O-Optimized if your I/O costs exceed 25% of your Aurora bill. Eliminates per-I/O charges for a fixed surcharge.
- Delete dev databases at night if your team doesn't work 24/7. Or use Serverless v2.
- Snapshot cleanup. Manual RDS snapshots accumulate. Set a retention policy.
Further Reading
Looking for hands-on help? View my AWS architecture services β