> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# RDS Aurora

> Deploy an AWS Aurora Serverless v2 PostgreSQL cluster with Fjall, including failover, encryption, and opt-in secret rotation.

## Overview

The RDS Aurora resource creates an Aurora Serverless v2 PostgreSQL cluster with automatic failover and storage encryption. Scheduled secret rotation and RDS Proxy connection pooling are opt-in features.

## Resource Class

```typescript theme={null}
import { RdsAurora } from "@fjall/components-infrastructure/lib/resources/aws/database/rdsAurora";
```

## Basic Usage

```typescript theme={null}
const database = new RdsAurora(this, "MyDatabase", {
  vpc: myVpc,
  databaseName: "myapp",
});
```

## Configuration Options

### Core Properties

| Property            | Type     | Description        | Default        |
| ------------------- | -------- | ------------------ | -------------- |
| `vpc`               | `IVpc`   | VPC for deployment | Required       |
| `databaseName`      | `string` | Database name      | Construct ID   |
| `clusterIdentifier` | `string` | Cluster identifier | Auto-generated |
| `port`              | `number` | Database port      | `35255`        |

### Engine Configuration

| Property       | Type             | Description                                           | Default                |
| -------------- | ---------------- | ----------------------------------------------------- | ---------------------- |
| `engine`       | `IClusterEngine` | Database engine                                       | Aurora PostgreSQL 16.6 |
| `engineConfig` | `EngineConfig`   | Engine-specific config (SSL params, default username) | PostgreSQL defaults    |

### Writer Configuration

| Property | Type                 | Description            | Default       |
| -------- | -------------------- | ---------------------- | ------------- |
| `writer` | `AuroraWriterConfig` | Writer instance config | Serverless v2 |

### Reader Configuration

| Property  | Type                           | Description      | Default                |
| --------- | ------------------------------ | ---------------- | ---------------------- |
| `readers` | `AuroraReadersConfig \| false` | Reader instances | 1 serverless v2 reader |

Pass `false` to create a cluster with no readers.

### Proxy Configuration

| Property | Type                   | Description                      | Default     |
| -------- | ---------------------- | -------------------------------- | ----------- |
| `proxy`  | `ProxyConfig \| false` | RDS Proxy for connection pooling | Not created |

RDS Proxy is opt-in. Pass a `ProxyConfig` object to enable it.

### Backup and Maintenance

| Property                     | Type       | Description                  | Default                 |
| ---------------------------- | ---------- | ---------------------------- | ----------------------- |
| `backupRetention`            | `number`   | Backup retention in days     | `14`                    |
| `monitoringInterval`         | `Duration` | Enhanced monitoring interval | 1 minute                |
| `preferredMaintenanceWindow` | `string`   | Maintenance window           | `"Sat:12:30-Sat:20:30"` |

### Security

| Property             | Type                     | Description                            | Default          |
| -------------------- | ------------------------ | -------------------------------------- | ---------------- |
| `encryption`         | `AuroraEncryptionConfig` | Storage and PI encryption keys         | AWS managed CMKs |
| `credentials`        | `CredentialsConfig`      | Username and rotation config           | Engine default   |
| `deletionProtection` | `boolean`                | Prevent accidental deletion            | `true`           |
| `allowVpcAccess`     | `boolean`                | Allow access from entire VPC CIDR      | `false`          |
| `publiclyAccessible` | `boolean`                | Place in public subnets                | `false`          |
| `allowedIpCidr`      | `string`                 | CIDR to allow when publicly accessible | -                |

### Snapshot Restore

| Property             | Type     | Description                        | Default |
| -------------------- | -------- | ---------------------------------- | ------- |
| `snapshotIdentifier` | `string` | Cluster snapshot identifier or ARN | -       |
| `snapshotUsername`   | `string` | Master username from the snapshot  | -       |

### Database Insights

| Property           | Type                              | Description            | Default |
| ------------------ | --------------------------------- | ---------------------- | ------- |
| `databaseInsights` | `DatabaseInsightsConfig \| false` | Performance monitoring | Enabled |

## Default Architecture

The default configuration creates:

* **1 Writer instance** (Serverless v2)
* **1 Reader instance** (Serverless v2, scales with writer)
* **Encryption** with AWS KMS CMKs
* **Database Insights** enabled
* **Deletion protection** enabled
* **IAM authentication** enabled

RDS Proxy is **not** created by default. Enable it by passing a `proxy` configuration.

Secret rotation is **not** enabled by default. Opt in by passing a rotation config (`credentials: { secretRotation: {} }` for the 30-day default). Rotation uses the multi-user strategy, which requires a one-time manual step after deploy: populate the generated `<id>/master-secret` with valid superuser credentials as JSON. Until that secret is populated, every rotation attempt fails and the database password stays unchanged — a synth-time warning reminds you of this when rotation is enabled.

## Restoring from Snapshot

Create a new Aurora cluster from an existing cluster snapshot.

```typescript theme={null}
const database = new RdsAurora(this, "RestoredCluster", {
  vpc: myVpc,
  databaseName: "restored",
  snapshotIdentifier: "rds:my-aurora-cluster-snapshot",
  snapshotUsername: "postgres",
});
```

<Warning>
  **Key constraints when restoring from a snapshot:**

  * The **master username** is immutable and baked into the snapshot. `snapshotUsername` must match the original cluster's username exactly.
  * The **engine version** is inherited from the snapshot. A mismatch between the snapshot's engine version and the infrastructure code will cause a CloudFormation failure.
  * The **master password is reset** shortly after the restore. Fjall generates a new credentials secret for the restored cluster, and CloudFormation applies its password once the cluster becomes available (the cluster briefly reports `resetting-master-credentials`). The snapshot-era password stops working at that point — applications must read credentials from the generated secret.
</Warning>

<Note>
  This password reset only applies to restores performed through infrastructure code (`snapshotIdentifier`). Restores performed through AWS Backup (`fjall restore rds`) run outside CloudFormation and **keep the snapshot-era password** — see [fjall restore](/cli/restore).
</Note>

## Security Features

### Encryption

All data is encrypted using Customer Managed Keys (CMKs) for both storage and Performance Insights.

### Network Security

```typescript theme={null}
// Deployed in private subnets by default
const database = new RdsAurora(this, "Database", {
  vpc: vpc,
  databaseName: "secure",
});

// Allow access from application
application.connections.allowTo(
  database,
  Port.tcp(35255),
  "Application to database",
);
```

### Secret Management

```typescript theme={null}
const database = new RdsAurora(this, "Database", {
  vpc: vpc,
  databaseName: "myapp",
});

// Access credentials
const credentials = database.getCredentials();
const endpoint = database.getHostEndpoint();
const port = database.getHostPort();
```

## Reader Configuration

### Default (1 Reader)

```typescript theme={null}
// Creates 1 reader that scales with the writer
const database = new RdsAurora(this, "Database", {
  vpc: vpc,
  databaseName: "myapp",
});
```

### Multiple Readers

```typescript theme={null}
const database = new RdsAurora(this, "ScaledDatabase", {
  vpc: vpc,
  databaseName: "scaled",
  readers: {
    count: 3,
  },
});
```

### No Readers

```typescript theme={null}
const database = new RdsAurora(this, "WriterOnly", {
  vpc: vpc,
  databaseName: "writeronly",
  readers: false,
});
```

## RDS Proxy

RDS Proxy is opt-in. Enable it for connection pooling, failover handling, and reduced database connections.

```typescript theme={null}
const database = new RdsAurora(this, "ProxiedDatabase", {
  vpc: vpc,
  databaseName: "proxied",
  proxy: {
    requireTLS: true,
    connectionBorrowTimeout: 120,
    maxConnections: 80,
    maxIdleConnections: 50,
  },
});

// When proxy is enabled, getHostEndpoint() returns the proxy endpoint
const endpoint = database.getHostEndpoint();
```

When proxy is disabled (the default), `getHostEndpoint()` returns the cluster endpoint directly.

## Backup and Recovery

### Custom Backup Retention

```typescript theme={null}
const database = new RdsAurora(this, "BackupDatabase", {
  vpc: vpc,
  databaseName: "backup",
  backupRetention: 30,
});
```

### Point-in-Time Recovery

Aurora supports PITR for any point within the backup retention period:

* Continuous backup to S3
* Restore to any second within retention period
* Cross-region backup replication available

## Monitoring

### Enhanced Monitoring

```typescript theme={null}
const database = new RdsAurora(this, "MonitoredDatabase", {
  vpc: vpc,
  databaseName: "monitored",
  monitoringInterval: Duration.seconds(10),
});
```

### Database Insights

Enabled by default on all instances. Provides:

* SQL-level performance metrics
* Top SQL statements
* Database load by waits

## Methods

### Get Host Endpoint

```typescript theme={null}
const endpoint = database.getHostEndpoint();
// Returns: Proxy endpoint if proxy enabled, otherwise cluster endpoint
```

### Get Host Port

```typescript theme={null}
const port = database.getHostPort();
// Returns: "35255" (default, as string)
```

### Get Credentials

```typescript theme={null}
const credentials = database.getCredentials();
// Returns: Secret object containing username/password
```

### Get Connections

```typescript theme={null}
const connections = database.connections;
// Use for network access control
```

### Get Database Cluster

```typescript theme={null}
const cluster = database.getDatabaseCluster();
// Returns: DatabaseCluster (CDK construct)
```

### Get CFN Cluster

```typescript theme={null}
const cfnCluster = database.getCfnCluster();
// Returns: CfnDBCluster | undefined
```

## Complete Example

```typescript theme={null}
import { RdsAurora } from "@fjall/components-infrastructure/lib/resources/aws/database/rdsAurora";
import { Duration } from "aws-cdk-lib";
import { Vpc, Port } from "aws-cdk-lib/aws-ec2";
import { CfnOutput } from "aws-cdk-lib";

// Create VPC
const vpc = new Vpc(this, "AppVpc", {
  maxAzs: 3,
  natGateways: 1,
});

// Create database with proxy
const database = new RdsAurora(this, "ProductionDatabase", {
  vpc: vpc,
  databaseName: "production",
  clusterIdentifier: "prod-cluster",

  // Backup
  backupRetention: 35,

  // Maintenance
  preferredMaintenanceWindow: "Sun:03:00-Sun:04:00",

  // Monitoring
  monitoringInterval: Duration.seconds(10),

  // Enable proxy for connection pooling
  proxy: {
    requireTLS: true,
  },

  // Reader configuration
  readers: {
    count: 2,
  },
});

// Allow connection from application
app.connections.allowTo(database, Port.tcp(35255), "Application to database");

// Output endpoint
new CfnOutput(this, "DatabaseEndpoint", {
  value: database.getHostEndpoint(),
  description: "Database endpoint (proxy if enabled)",
});
```

## Cost Optimisation

### Serverless v2 Scaling

* **ACU (Aurora Capacity Units)**: 0.5 - 1 ACU minimum
* **Automatic scaling**: Based on workload
* **Per-second billing**: Pay only for usage
* **Reader scaling**: Configure based on read patterns

### Cost Comparison

| Configuration   | Monthly Cost (Estimate) |
| --------------- | ----------------------- |
| 0.5 ACU minimum | \~\$43                  |
| 1 ACU minimum   | \~\$87                  |
| 2 ACU minimum   | \~\$174                 |
| With 1 reader   | 2x base cost            |

## Best Practices

1. **Enable RDS Proxy** when your application has many short-lived connections
2. **Database Insights** is enabled by default for monitoring
3. **Configure appropriate backup retention** (default 14 days)
4. **Use readers for analytics** and reporting queries
5. **Monitor ACU usage** to optimise costs
6. **Deletion protection** is enabled by default for production safety
7. **Review security group rules** regularly

## Limitations

* Minimum 0.5 ACU per instance (\~\$43/month)
* PostgreSQL 16.6 (upgrades require planning)
* Cross-region replicas require Global Database (see RdsAuroraGlobal)

## Next Steps

<CardGroup cols={2}>
  <Card title="RDS Instance" icon="database" href="/resources/database/rds-instance">
    Deploy a single-instance PostgreSQL or MySQL database when you do not need Serverless v2 scaling.
  </Card>

  <Card title="Database Factory" icon="layer-group" href="/patterns/database-factory">
    Provision Aurora, RDS Instance, DynamoDB, or ClickHouse from one declarative factory.
  </Card>

  <Card title="Security Group" icon="shield-halved" href="/resources/networking/security-group">
    Control which applications and CIDRs can reach the cluster on port 35255.
  </Card>

  <Card title="Secrets Manager" icon="key" href="/resources/security/secrets-manager">
    Read the generated database credentials and configure rotation.
  </Card>
</CardGroup>
