AWS Aurora
AWS Aurora Serverless v2, RDS Proxy, Data API, connection pooling
MCP get_skill({ skillId: "aws-aurora-skill-6df9b24f" })Use this skill with your agent
Create a free account and connect via MCP
# AWS Aurora Skill
Amazon Aurora is a MySQL/PostgreSQL-compatible relational database with serverless scaling, high availability, and enterprise features.
**Sources:** [Aurora Docs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/) | [Serverless v2](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.html) | [RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html)
---
## Core Principle
**Use RDS Proxy for serverless, Data API for simplicity, connection pooling always.**
Aurora excels at ACID-compliant workloads. For serverless architectures (Lambda), always use RDS Proxy or Data API to handle connection management. Never open raw connections from Lambda functions.
---
## Aurora Options
| Option | Best For |
|--------|----------|
| **Aurora Serverless v2** | Variable workloads, auto-scaling (0.5-128 ACUs) |
| **Aurora Provisioned** | Predictable workloads, maximum performance |
| **Aurora Global** | Multi-region, disaster recovery |
| **Data API** | Serverless without VPC, simple HTTP access |
| **RDS Proxy** | Connection pooling for Lambda, high concurrency |
---
## Connection Strategies
### Strategy 1: RDS Proxy (Recommended for Lambda)
```
Lambda → RDS Proxy → Aurora
(pool)
```
- Connection pooling and reuse
- Automatic failover handling
- IAM authentication support
- Works with existing SQL clients
### Strategy 2: Data API (Simplest for Serverless)
```
Lambda → Data API (HTTP) → Aurora
```
- No VPC required
- No connection management
- Higher latency per query
- Limited to Aurora Serverless
### Strategy 3: Direct Connection (Not for Lambda)
```
App Server → Aurora
(persistent connection)
```
- Only for long-running servers (ECS, EC2)
- Manage connection pool yourself
- Not suitable for serverless
---
## RDS Proxy Setup
### Create Proxy (AWS Console/CDK)
```typescript
// CDK example
import * as rds from 'aws-cdk-lib/aws-rds';
const proxy = new rds.DatabaseProxy(this, 'Proxy', {
proxyTarget: rds.ProxyTarget.fromCluster(cluster),
secrets: [cluster.secret!],
vpc,
securityGroups: [proxySecurityGroup],
requireTLS: true,
idleClientTimeout: cdk.Duration.minutes(30),
maxConnectionsPercent: 90,
maxIdleConnectionsPercent: 10,
borrowTimeout: cdk.Duration.seconds(30)
});
```
### Connect via Proxy (TypeScript/Node.js)
```typescript
// lib/db.ts
import { Pool } from 'pg';
import { Signer } from '@aws-sdk/rds-signer';
const signer = new Signer({
hostname: process.env.RDS_PROXY_ENDPOINT!,
port: 5432,
username: process.env.DB_USER!,
region: process.env.AWS_REGION!
});
// IAM authentication
async function getPool(): Promise<Pool> {
const token = await signer.getAuthToken();
return new Pool({
host: process.env.RDS_PROXY_ENDPOINT,
port: 5432,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: token,
ssl: { rejectUnauthorized: true },
max: 1, // Single connection for Lambda
idleTimeoutMillis: 120000,
connectionTimeoutMillis: 10000
});
}
// Usage in Lambda
let pool: Pool | null = null;
export async function handler(event: any) {
if (!pool) {
pool = await getPool();
}
const result = await pool.query('SELECT * FROM users WHERE id = $1', [event.userId]);
return result.rows[0];
}
```
### Proxy Configuration Best Practices
```bash
# Key settings for Lambda workloads
MaxConnectionsPercent: 90 # Use most of DB connections
MaxIdleConnectionsPercent: 10 # Keep some idle for bursts
ConnectionBorrowTimeout: 30s # Wait for available connection
IdleClientTimeout: 30min # Close idle proxy connections
# Monitor these CloudWatch metrics:
# - DatabaseConnectionsCurrentlyBorrowed
# - DatabaseConnectionsCurrentlySessionPinned
# - QueryDatabaseResponseLatency
```
---
## Data API (HTTP-based)
### Enable Data API
```bash
# Must be Aurora Serverless
aws rds modify-db-cluster \
--db-cluster-identifier my-cluster \
--enable-http-endpoint
```
### TypeScript with Data API Client v2
```bash
npm install data-api-client
```
```typescript
// lib/db.ts
import DataAPIClient from 'data-api-client';
const db = DataAPIClient({
secretArn: process.env.DB_SECRET_ARN!,
resourceArn: process.env.DB_CLUSTER_ARN!,
database: process.env.DB_NAME!,
region: process.env.AWS_REGION!
});
// Simple query
const users = await db.query('SELECT * FROM users WHERE active = :active', {
active: true
});
// Insert with returning
const result = await db.query(
'INSERT INTO users (email, name) VALUES (:email, :name) RETURNING *',
{ email: 'user@test.com', name: 'Test User' }
);
// Transaction
const transaction = await db.transaction();
try {
await transaction.query('UPDATE accounts SET balance = balance - :amount WHERE id = :from', {
amount: 100, from: 1
});
await transaction.query('UPDATE accounts SET balance = balance + :amount WHERE id = :to', {
amount: 100, to: 2
});
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
```
### Python with boto3
```python
# requirements.txt
boto3>=1.34.0
# db.py
import boto3
import os
rds_data = boto3.client('rds-data')
CLUSTER_ARN = os.environ['DB_CLUSTER_ARN']
SECRET_ARN = os.environ['DB_SECRET_ARN']
DATABASE = os.environ['DB_NAME']
def execute_sql(sql: str, parameters: list = None):
"""Execute SQL via Data API."""
params = {
'resourceArn': CLUSTER_ARN,
'secretArn': SECRET_ARN,
'database': DATABASE,
'sql': sql
}
if parameters:
params['parameters'] = parameters
return rds_data.execute_statement(**params)
def get_user(user_id: int):
result = execute_sql(
'SELECT * FROM users WHERE id = :id',
[{'name': 'id', 'value': {'longValue': user_id}}]
)
return result.get('records', [])
def create_user(email: str, name: str):
result = execute_sql(
'INSERT INTO users (email, name) VALUES (:email, :name) RETURNING *',
[
{'name': 'email', 'value': {'stringValue': email}},
{'name': 'name', 'value': {'stringValue': name}}
]
)
return result.get('generatedFields')
# Transaction
def transfer_funds(from_id: int, to_id: int, amount: float):
transaction = rds_data.begin_transaction(
resourceArn=CLUSTER_ARN,
secretArn=SECRET_ARN,
database=DATABASE
)
transaction_id = transaction['transactionId']
try:
execute_sql(
'UPDATE accounts SET balance = balance - :amount WHERE id = :id',
[
{'name': 'amount', 'value': {'doubleValue': amount}},
{'name': 'id', 'value': {'longValue': from_id}}
]
)
execute_sql(
'UPDATE accounts SET balance = balance + :amount WHERE id = :id',
[
{'name': 'amount', 'value': {'doubleValue': amount}},
{'name': 'id', 'value': {'longValue': to_id}}
]
)
rds_data.commit_transaction(
resourceArn=CLUSTER_ARN,
secretArn=SECRET_ARN,
transactionId=transaction_id
)
except Exception as e:
rds_data.rollback_transaction(
resourceArn=CLUSTER_ARN,
secretArn=SECRET_ARN,
transactionId=transaction_id
)
raise e
```
---
## Prisma with Aurora
### Setup (VPC Connection via RDS Proxy)
```bash
npm install prisma @prisma/client
npx prisma init
```
```prisma
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
}
```
### Environment
```bash
# Use RDS Proxy endpoint
DATABASE_URL="postgresql://user:password@proxy-endpoint.proxy-xxx.region.rds.amazonaws.com:5432/mydb?schema=public&connection_limit=1"
```
### Lambda Handler with Prisma
```typescript
// handlers/users.ts
import { PrismaClient } from '@prisma/client';
// Reuse client across invocations
let prisma: PrismaClient | null = null;
function getPrisma(): PrismaClient {
if (!prisma) {
prisma = new PrismaClient({
datasources: {
db: { url: process.env.DATABASE_URL }
}
});
}
return prisma;
}
export async function handler(event: any) {
const db = getPrisma();
const users = await db.user.findMany({
include: { posts: true },
take: 10
});
return {
statusCode: 200,
body: JSON.stringify(users)
};
}
```
---
## Aurora Serverless v2
### Capacity Configuration
```typescript
// CDK
const cluster = new rds.DatabaseCluster(this, 'Cluster', {
engine: rds.DatabaseClusterEngine.auroraPostgres({
version: rds.AuroraPostgresEngineVersion.VER_15_4
}),
serverlessV2MinCapacity: 0.5, // Minimum ACUs
serverlessV2MaxCapacity: 16, // Maximum ACUs
writer: rds.ClusterInstance.serverlessV2('writer'),
readers: [
rds.ClusterInstance.serverlessV2('reader', { scaleWithWriter: true })
],
vpc,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }
});
```
### Capacity Guidelines
| Workload | Min ACUs | Max ACUs |
|----------|----------|----------|
| Dev/Test | 0.5 | 2 |
| Small Production | 2 | 8 |
| Medium Production | 4 | 32 |
| Large Production | 8 | 128 |
### Handle Scale-to-Zero Wake-up
```typescript
// Data API Client v2 handles this automatically
// For direct connections, implement retry logic:
import { Pool } from 'pg';
async function queryWithRetry(
pool: Pool,
sql: string,
params: any[],
maxRetries = 3
): Promise<any> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await pool.query(sql, params);
} catch (error: any) {
// Aurora Serverless waking up
if (error.code === 'ETIMEDOUT' || error.message?.includes('Communications link failure')) {
if (attempt === maxRetries) throw error;
// Exponential backoff
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
continue;
}
throw error;
}
}
}
```
---
## Migrations
### Using Prisma Migrate
```bash
# Development (creates migration)
npx prisma migrate dev --name add_users_table
# Production (apply migrations)
npx prisma migrate deploy
# Generate client
npx prisma generate
```
### CI/CD Migration Script
```yaml
# .github/workflows/deploy.yml
- name: Run migrations
run: |
# Connect via bastion or use a migration Lambda
npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
```
### Migration Lambda
```typescript
// lambdas/migrate.ts
import { execSync } from 'child_process';
export async function handler() {
try {
execSync('npx prisma migrate deploy', {
env: {
...process.env,
DATABASE_URL: process.env.DATABASE_URL
},
stdio: 'inherit'
});
return { statusCode: 200, body: 'Migrations applied' };
} catch (error) {
console.error('Migration failed:', error);
throw error;
}
}
```
---
## Connection Pooling (Non-Lambda)
### PgBouncer Sidecar (ECS/EKS)
```yaml
# docker-compose.yml
services:
app:
build: .
environment:
DATABASE_URL: postgresql://user:pass@pgbouncer:6432/mydb
pgbouncer:
image: edoburu/pgbouncer
environment:
DATABASE_URL: postgresql://user:pass@aurora-endpoint:5432/mydb
POOL_MODE: transaction
MAX_CLIENT_CONN: 1000
DEFAULT_POOL_SIZE: 20
```
### Application-Level Pooling
```typescript
// For long-running servers (not Lambda)
import { Pool } from 'pg';
const pool = new Pool({
host: process.env.DB_HOST,
port: 5432,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
max: 20, // Max connections
idleTimeoutMillis: 30000, // Close idle after 30s
connectionTimeoutMillis: 10000
});
// Use pool for all queries
export async function query(sql: string, params?: any[]) {
const client = await pool.connect();
try {
return await client.query(sql, params);
} finally {
client.release();
}
}
```
---
## Monitoring
### Key CloudWatch Metrics
```
# Aurora
- CPUUtilization
- DatabaseConnections
- FreeableMemory
- ServerlessDatabaseCapacity (ACUs)
- AuroraReplicaLag
# RDS Proxy
- DatabaseConnectionsCurrentlyBorrowed
- DatabaseConnectionsCurrentlySessionPinned
- QueryDatabaseResponseLatency
- ClientConnectionsReceived
```
### Performance Insights
```bash
# Enable via console or CLI
aws rds modify-db-cluster \
--db-cluster-identifier my-cluster \
--enable-performance-insights \
--performance-insights-retention-period 7
```
---
## Security
### IAM Database Authentication
```typescript
import { Signer } from '@aws-sdk/rds-signer';
const signer = new Signer({
hostname: process.env.DB_HOST!,
port: 5432,
username: 'iam_user',
region: 'us-east-1'
});
const token = await signer.getAuthToken();
// Use token as password (valid for 15 minutes)
const pool = new Pool({
host: process.env.DB_HOST,
user: 'iam_user',
password: token,
ssl: true
});
```
### Secrets Manager Rotation
```typescript
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: 'us-east-1' });
async function getDbCredentials() {
const response = await client.send(
new GetSecretValueCommand({ SecretId: process.env.DB_SECRET_ARN })
);
return JSON.parse(response.SecretString!);
}
```
---
## CLI Quick Reference
```bash
# Cluster operations
aws rds describe-db-clusters
aws rds create-db-cluster --engine aurora-postgresql --db-cluster-identifier my-cluster
aws rds delete-db-cluster --db-cluster-identifier my-cluster --skip-final-snapshot
# Serverless v2
aws rds modify-db-cluster \
--db-cluster-identifier my-cluster \
--serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=16
# Data API
aws rds-data execute-statement \
--resource-arn $CLUSTER_ARN \
--secret-arn $SECRET_ARN \
--database mydb \
--sql "SELECT * FROM users"
# Proxy
aws rds describe-db-proxies
aws rds create-db-proxy --db-proxy-name my-proxy --engine-family POSTGRESQL ...
# Snapshots
aws rds create-db-cluster-snapshot --db-cluster-identifier my-cluster --db-cluster-snapshot-identifier backup-1
aws rds restore-db-cluster-from-snapshot --db-cluster-identifier restored --snapshot-identifier backup-1
```
---
## Anti-Patterns
- **Direct Lambda→Aurora connections** - Always use RDS Proxy or Data API
- **No connection limits** - Set `max: 1` for Lambda, use pooling for servers
- **Ignoring cold starts** - Serverless v2 needs time to scale; keep minimum ACUs for production
- **No read replicas** - Offload reads to replicas for heavy workloads
- **Missing IAM auth** - Use IAM over static passwords when possible
- **No retry logic** - Handle transient errors from scaling/failover
- **Over-provisioned capacity** - Use Serverless v2 for variable workloads
- **Skipping Secrets Manager** - Never hardcode credentialsRelated Skills
More skills in DevOps & Cloud
1password Skill
1password Skill linked from Juliano Barbosa Claude Code Skills, with the upstream skill instructions available on GitHub.
Actions Manager
GitHub Actions command center -- view workflow runs, read logs, re-run failed jobs, manage workflows, and debug CI failures entirely from the editor. Bypasses the deeply nested, visually-dependent Actions UI that is largely inaccessible to screen readers.
Airunway Aks Setup
Set up AI Runway on AKS — from bare cluster to running model. Covers cluster verification, controller install, GPU assessment, provider setup, and first deployment. WHEN: "setup AI Runway", "onboard AKS cluster", "install AI Runway", "airunway setup", "deploy model to AKS", "GPU inference on AKS", "KAITO setup on AKS", "run LLM on AKS", "vLLM on AKS", "set up model serving on AKS", "AI Runway controller".
Alz Accelerator
Deploy Azure Landing Zones using the ALZ Accelerator with AVM (Azure Verified Modules). Use this skill whenever the user mentions Azure Landing Zones, ALZ, Azure landing zone accelerator, AVM modules for landing zones, deploying management groups, hub-and-spoke networking, Virtual WAN, platform landing zones, or asks about Bicep vs Terraform for Azure infrastructure. Also trigger when the user wants to bootstrap CI/CD for Azure platform deployment, set up management groups hierarchy, or deploy connectivity/identity/management platform subscriptions.
Alz Accelerator Skill
Alz Accelerator Skill linked from Juliano Barbosa Claude Code Skills, with the upstream skill instructions available on GitHub.
Ansible Conventions and Best Practices
Ansible conventions and best practices
Explore Other Categories
Skills from other categories with shared topics
Base
Universal coding patterns, constraints, TDD workflow, atomic todos
Icpg
Intent-Augmented Code Property Graph — tracks WHY code exists via ReasonNodes with formal contracts, 6-dimension drift detection, and 3 canonical pre-task queries for autonomous development
LLM Patterns
AI-first application patterns, LLM testing, prompt management