Aurora #
In the cloud computing world, traditional relational databases (like MySQL and PostgreSQL) often become the biggest bottleneck when an application starts scaling up. Storage scalability problems, complicated high-availability configuration, and slow failover recovery times are classic challenges that haunt database engineers.
AWS Aurora was created to redesign relational database architecture to be compatible with modern cloud characteristics. Aurora is AWS’s fully managed relational database compatible with MySQL and PostgreSQL, but with performance up to 5 times faster than standard MySQL and 3 times faster than standard PostgreSQL. This article will deeply dissect Aurora’s internal architecture, how Aurora Serverless (v1 & v2) works, the essential serverless database connection needs through RDS Proxy, and practical implementation guidance in the real world.
Aurora Distributed Storage Architecture #
The key to AWS Aurora’s outstanding performance and data durability lies in the clean separation between the Compute Layer (the engine processing SQL queries) and the Storage Layer (the data storage system).
flowchart TD
subgraph Compute["Compute Layer (Database Instance)"]
Writer["Writer Node (Primary)"]
Reader["Reader Node (Read Replica)"]
end
subgraph Storage["Storage Layer (Distributed Storage Volume)"]
direction TB
subgraph AZ1["Availability Zone 1"]
C1["Copy 1"]
C2["Copy 2"]
end
subgraph AZ2["Availability Zone 2"]
C3["Copy 3"]
C4["Copy 4"]
end
subgraph AZ3["Availability Zone 3"]
C5["Copy 5"]
C6["Copy 6"]
end
end
Writer -->|"Write Data (Log stream)"| Storage
Reader -->|Read Data| Storage1. Automatic Multi-AZ Replication #
Aurora storage is virtualized and distributed. When data is written to the database, Aurora automatically duplicates it into 6 data copies spread across 3 different Availability Zones (AZs).
2. Quorum Model (Write & Read Quorum) #
To guarantee data consistency over distributed storage, Aurora uses Quorum rules:
- Write Quorum (4/6): A write operation is considered successful if 4 of the 6 storage copies successfully write the data. This makes writes very fast because we don’t need to wait for the slowest data center’s response.
- Read Quorum (3/6): Read operations validate at least 3 of the 6 copies to ensure the data being read is the most up-to-date.
3. Storage Scaling Without Provisioning #
In traditional databases, we must determine the disk size upfront (e.g., 100 GB). If the disk fills up, the database crashes unless we manually add disk space. Aurora storage detects usage automatically and grows elastically up to 128 TB without triggering downtime or manual configuration.
Aurora Serverless: v1 vs. v2 #
AWS provides the Aurora Serverless option to free us from choosing the database server’s memory/CPU size upfront. Database capacity scales up and down automatically following query load fluctuations.
There are very significant architectural differences between the first generation (v1) and the second generation (v2):
1. Aurora Serverless v1 #
- Scaling Method: Uses step-based allocation (e.g., doubling capacity from 2 ACUs directly to 4 ACUs, then 8 ACUs). Scaling takes seconds to minutes because AWS must prepare new instances in the background.
- Auto-Pause Feature: Can scale down to 0 ACUs (Paused) if there’s no connection activity at all for a certain period (e.g., 5 minutes). When new requests arrive, the database wakes back up (resumes) with a cold start delay of about 10–25 seconds.
- Best Use Cases: Development, staging, or internal office application environments not used at night.
2. Aurora Serverless v2 (Recommended) #
- Scaling Method: Scaling runs instantly (milliseconds) and very smoothly (fine-grained), e.g., scaling from 1.2 ACUs to 1.3 ACUs dynamically following actual CPU workload.
- No Auto-Pause: v2 doesn’t support the auto-pause-to-zero feature. The minimum supported capacity is 0.5 ACUs (roughly ~1 GB RAM) to keep the database always active without cold start risk.
- Multi-AZ & Read Replica Features: v2 can be combined with Provisioned Readers and supports multi-region global database replication.
- Best Use Cases: Large-scale production workloads, public REST APIs with spiky traffic, e-commerce, and enterprise applications.
ACU (Aurora Capacity Unit) Definition: 1 ACU represents a memory allocation of ~2 GB RAM along with a proportionate amount of CPU compute power and network bandwidth.
Serverless Connectivity: The Role of RDS Proxy #
One of the biggest architectural problems when connecting FaaS functions (like AWS Lambda) directly to relational databases is connection exhaustion.
PostgreSQL or MySQL databases limit the number of active connections (usually a few hundred maximum). Every time a Lambda function is invoked, it opens a new connection to the database. If a traffic spike triggers 1,000 Lambda instances running in parallel, the database runs out of connections instantly and rejects subsequent transactions (connection refused).
flowchart TD
subgraph LambdaSpike["Lambda Scaling Cycle (Spiky)"]
L1["Lambda Instance 1"]
L2["Lambda Instance 2"]
L3["Lambda Instance N"]
end
subgraph VPC["Virtual Private Cloud"]
Proxy["Amazon RDS Proxy<br/>(Manages Connection Pool)"]
subgraph AuroraCluster["Aurora Serverless v2 Cluster"]
DBWriter["Writer Node<br/>(Scaling: 0.5 - 16 ACU)"]
DBReader["Reader Node<br/>(Read Replica)"]
end
L1 -->|Short Connection| Proxy
L2 -->|Short Connection| Proxy
L3 -->|Short Connection| Proxy
Proxy -->|Stable Connection Pool| DBWriter
Proxy -->|Stable Connection Pool| DBReader
endAmazon RDS Proxy Advantages: #
- Connection Pooling: RDS Proxy sits between Lambda and the database. It manages thousands of connections from Lambda and channels them back to the database through a small pool of stable, persistent database connections.
- Failover Speed: If the Aurora writer node fails, RDS Proxy automatically redirects connections to the reader node (promoted to become the new writer) without breaking application connections on the Lambda side.
Implementation Code Example: Connection via RDS Proxy #
Here’s a Node.js code example demonstrating how to safely connect a Lambda function to an Aurora PostgreSQL database using RDS Proxy and automatically retrieve database credentials from AWS Secrets Manager using an IAM token.
// CORRECT: Using RDS Proxy + Secrets Manager + IAM Database Token
import { PG } from 'pg';
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
const secretsClient = new SecretsManagerClient({ region: "ap-southeast-1" });
const SECRET_ARN = process.env.DB_SECRET_ARN;
const PROXY_ENDPOINT = process.env.RDS_PROXY_ENDPOINT;
let dbClient = null;
async function getDatabaseCredentials() {
console.log("Retrieving database credentials from Secrets Manager...");
const data = await secretsClient.send(new GetSecretValueCommand({ SecretId: SECRET_ARN }));
return JSON.parse(data.SecretString);
}
async function initializeDbClient() {
if (!dbClient) {
const credentials = await getDatabaseCredentials();
dbClient = new PG.Client({
host: PROXY_ENDPOINT, // ✓ Connecting to the RDS Proxy endpoint, not the database directly
port: 5432,
database: credentials.dbname,
user: credentials.username,
password: credentials.password,
ssl: {
rejectUnauthorized: true // ✓ Always enable SSL certificate verification in production
}
});
await dbClient.connect();
console.log("Successfully connected to the database via RDS Proxy.");
}
}
export const handler = async (event) => {
try {
await initializeDbClient();
const result = await dbClient.query("SELECT NOW()");
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
success: true,
dbTime: result.rows[0].now
})
};
} catch (error) {
console.error("Database connection error", error);
return {
statusCode: 500,
body: JSON.stringify({ error: "Failed to process data" })
};
}
};
Summary #
← Previous: Step Functions Next: API Gateway →
- AWS Aurora cleanly separates the Compute and Storage layers, duplicating data 6 times across 3 AZs and auto-scaling disk size up to 128 TB.
- Aurora Serverless v2 offers very instant and smooth compute scalability (in milliseconds) based on ACUs (Aurora Capacity Units) with a minimum limit of 0.5 ACUs.
- Aurora Serverless v1 supports the auto-pause feature down to 0 ACUs, but has a cold start delay constraint when waking back up.
- Amazon RDS Proxy is highly recommended for serverless (Lambda) applications to prevent connection exhaustion through its connection pooling feature.
- Implement IAM Database Authentication security and Secrets Manager integration to secure database credential token exchange at runtime.