> ## 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 Instance

> Deploy a managed AWS RDS PostgreSQL instance with Fjall: Multi-AZ failover, encryption, automated backups, and read replicas.

## Overview

The `RdsInstance` construct provisions a managed PostgreSQL database instance with Multi-AZ deployment, encryption, automated backups, and optional read replicas. It suits applications that want predictable performance and cost.

## Resource Class

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

## Basic Usage

```typescript theme={null}
const database = new RdsInstance(this, "MyDatabase", {
  vpc: myVpc,
  databaseName: "myapp",
  instanceType: "t4g.medium",
});
```

<Note>
  `instanceType` takes the bare class.size form (`t4g.medium`, `r6g.large`), not the `db.`-prefixed form. The construct passes the value straight to `new InstanceType(...)`, so a `db.` prefix produces an invalid instance class.
</Note>

## Configuration Options

### Core Properties

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

### Engine Configuration

| Property | Type              | Description     | Default         |
| -------- | ----------------- | --------------- | --------------- |
| `engine` | `IInstanceEngine` | Database engine | PostgreSQL 17.5 |

### Instance Configuration

| Property              | Type     | Description                          | Default        |
| --------------------- | -------- | ------------------------------------ | -------------- |
| `instanceType`        | `string` | Instance type (bare class.size form) | `"t4g.large"`  |
| `allocatedStorage`    | `number` | Initial storage in GB                | Engine default |
| `maxAllocatedStorage` | `number` | Max autoscaling storage              | `500` GB       |

<Note>
  When Fjall provisions a database through an application tier, the instance type defaults vary: `t4g.micro` (Tinkerer), `t4g.small` (Lightweight), `t4g.large` (Standard), `r7g.large` (Resilient), `r6g.xlarge` (Enterprise). When using the construct directly, set `instanceType` explicitly.
</Note>

### Backup and Maintenance

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

### Snapshot Restore

| Property             | Type     | Description                                    | Default |
| -------------------- | -------- | ---------------------------------------------- | ------- |
| `snapshotIdentifier` | `string` | RDS snapshot identifier or ARN to restore from | -       |
| `snapshotUsername`   | `string` | Master username baked into the snapshot        | -       |

### Additional Features

| Property             | Type                              | Description                  | Default |
| -------------------- | --------------------------------- | ---------------------------- | ------- |
| `proxy`              | `ProxyConfig \| false`            | RDS Proxy connection pooling | -       |
| `readReplica`        | `ReadReplicaConfig \| false`      | Read replica                 | -       |
| `databaseInsights`   | `DatabaseInsightsConfig \| false` | Database Insights monitoring | Enabled |
| `multiAz`            | `boolean`                         | Multi-AZ deployment          | `true`  |
| `deletionProtection` | `boolean`                         | Deletion protection          | `true`  |
| `securityGroupIds`   | `string[]`                        | Additional security groups   | `[]`    |

## Restoring from Snapshot

Create a new database from an existing RDS snapshot:

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

<Warning>
  Constraints when restoring from a snapshot:

  * The master username is immutable and baked into the snapshot. `snapshotUsername` must match the original database's username exactly.
  * The engine version is inherited from the snapshot. A mismatch between the snapshot's engine version and the infrastructure code causes a CloudFormation failure.
  * The storage size cannot be smaller than the snapshot's allocated storage.
  * The master password is reset shortly after the restore. Fjall generates a new credentials secret for the restored instance, and CloudFormation applies its password once the instance becomes available (the instance 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>

You can also add the resource from the CLI with snapshot restore configured:

```bash theme={null}
fjall add database --app api --name RestoredDB --type Instance \
  --snapshot-identifier rds:my-production-snapshot \
  --snapshot-username postgres
```

## Instance Types

### General Purpose (Burstable)

```typescript theme={null}
const devDatabase = new RdsInstance(this, "DevDB", {
  vpc: vpc,
  databaseName: "development",
  instanceType: "t4g.micro", // 2 vCPU, 1 GB RAM
});
```

### General Purpose (Standard)

```typescript theme={null}
const prodDatabase = new RdsInstance(this, "ProdDB", {
  vpc: vpc,
  databaseName: "production",
  instanceType: "m6g.large", // 2 vCPU, 8 GB RAM
});
```

### Memory Optimised

```typescript theme={null}
const perfDatabase = new RdsInstance(this, "PerfDB", {
  vpc: vpc,
  databaseName: "performance",
  instanceType: "r6g.xlarge", // 4 vCPU, 32 GB RAM
});
```

## Storage Configuration

### Auto-scaling Storage

```typescript theme={null}
const database = new RdsInstance(this, "AutoScaleDB", {
  vpc: vpc,
  databaseName: "autoscale",
  allocatedStorage: 100, // Start with 100 GB
  maxAllocatedStorage: 1000, // Scale up to 1 TB
});
```

### Storage Type

All instances use GP3 storage by default:

* Baseline: 3,000 IOPS
* Burst: up to 16,000 IOPS
* Throughput: 125 MiB/s baseline

## Security Features

### Encryption

Storage encryption is on by default with a customer-managed KMS key. Performance Insights data is encrypted when Database Insights is enabled.

```typescript theme={null}
const database = new RdsInstance(this, "EncryptedDB", {
  vpc: vpc,
  databaseName: "secure",
});
```

### Network Security

```typescript theme={null}
const database = new RdsInstance(this, "SecureDB", {
  vpc: vpc,
  databaseName: "secure",
});

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

// Add additional security groups
const adminDatabase = new RdsInstance(this, "MultiSecDB", {
  vpc: vpc,
  databaseName: "multisec",
  securityGroupIds: [adminSG.securityGroupId],
});
```

## High Availability

### Multi-AZ Deployment

Multi-AZ is enabled by default. Set `multiAz: false` to opt out.

```typescript theme={null}
const database = new RdsInstance(this, "HADB", {
  vpc: vpc,
  databaseName: "highavail",
  // multiAz: true (default)
});
```

Benefits:

* Automatic failover (1-2 minutes)
* Synchronous replication
* Maintenance without downtime
* Enhanced durability

## RDS Proxy

Enable connection pooling by passing a `ProxyConfig` object. `ProxyConfig` fields: `requireTLS`, `maxConnections`, `maxIdleConnections`, `connectionBorrowTimeout`, `vpcSubnets`.

```typescript theme={null}
const database = new RdsInstance(this, "ProxyDB", {
  vpc: vpc,
  databaseName: "pooled",
  proxy: {
    requireTLS: true,
  },
});

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

Benefits:

* Reduced database connections
* Improved application scalability
* Automatic failover handling
* IAM authentication support

## Read Replicas

Enable a read replica by passing a `ReadReplicaConfig` object. `ReadReplicaConfig` fields: `instanceType`, `availabilityZone`. Pass `{}` to inherit the primary's instance type.

```typescript theme={null}
const database = new RdsInstance(this, "ScaledDB", {
  vpc: vpc,
  databaseName: "scaled",
  readReplica: {
    instanceType: "t4g.large",
  },
});
```

Read replica features:

* Asynchronous replication
* Read-only queries
* Can be promoted to primary
* Cross-region support

## Database Insights

Database Insights (formerly Performance Insights) is enabled by default. Pass a `DatabaseInsightsConfig` object to set the mode, or `false` to disable it. `DatabaseInsightsConfig` fields: `mode` (`"standard"` or `"advanced"`), `encryptionKey`.

```typescript theme={null}
const database = new RdsInstance(this, "MonitoredDB", {
  vpc: vpc,
  databaseName: "monitored",
  databaseInsights: {
    mode: "advanced",
  },
});
```

Features:

* SQL-level performance metrics
* 7 days retention in standard mode, 15 months in advanced mode
* Top SQL identification
* Wait event analysis

## Backup and Recovery

### Custom Backup Configuration

```typescript theme={null}
const database = new RdsInstance(this, "BackupDB", {
  vpc: vpc,
  databaseName: "backup",
  backupRetention: Duration.days(30), // 30-day retention
});
```

### Automated Backups

* Daily automated backups
* Point-in-time recovery
* Transaction log backups every 5 minutes
* Backups retained after deletion

## Methods

### Get Host Endpoint

```typescript theme={null}
const endpoint = database.getHostEndpoint();
// Returns the proxy endpoint if a proxy is enabled, otherwise the instance endpoint
```

### Get Host Port

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

### Get Credentials

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

### Get Connections

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

### Get Security Group

```typescript theme={null}
const securityGroup = database.databaseSecurityGroup;
// Access the database security group
```

## Complete Example

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

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

// Create production database
const database = new RdsInstance(this, "ProductionDatabase", {
  vpc: vpc,
  databaseName: "production",

  // Instance configuration
  instanceType: "r6g.large", // Memory optimised
  allocatedStorage: 200, // 200 GB initial
  maxAllocatedStorage: 1000, // Scale to 1 TB

  // High availability
  proxy: {
    // Connection pooling
    requireTLS: true,
  },
  readReplica: {
    // Read scaling
    instanceType: "r6g.large",
  },

  // Monitoring
  databaseInsights: {
    mode: "advanced",
  },
  monitoringInterval: Duration.seconds(10),

  // Backup
  backupRetention: Duration.days(30),
  preferredMaintenanceWindow: "Sun:03:00-Sun:04:00",
});

// Create application
const app = new EcsCluster(this, "App", {
  vpc: vpc,
  serviceName: "app",
  containerEnvironment: {
    DB_HOST: database.getHostEndpoint(),
    DB_PORT: database.getHostPort(),
    DB_NAME: "production",
  },
  containerSecretsImport: {
    DB_PASSWORD: database.getCredentials().getImport("password"),
  },
});

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

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

## Cost Optimisation

### Instance Sizing

| Instance Type | vCPUs | Memory | Monthly Cost\* |
| ------------- | ----- | ------ | -------------- |
| t4g.micro     | 2     | 1 GB   | \~\$12         |
| t4g.small     | 2     | 2 GB   | \~\$23         |
| t4g.medium    | 2     | 4 GB   | \~\$46         |
| m6g.large     | 2     | 8 GB   | \~\$110        |
| r6g.large     | 2     | 16 GB  | \~\$140        |
| r6g.xlarge    | 4     | 32 GB  | \~\$280        |

\*Estimates for us-east-1, Multi-AZ deployment.

### Cost Saving Tips

1. **Use Graviton instances** (t4g, r6g, m6g) for up to 20% savings.
2. **Reserved Instances** for 1-3 year commitments.
3. **Right-size** based on CloudWatch metrics.
4. **Consider Aurora** for variable workloads.
5. **Optimise storage size** to avoid over-provisioning.

## Best Practices

1. Keep Multi-AZ on for production (default).
2. Use memory-optimised instance types (r6g) for production.
3. Monitor storage usage and keep autoscaling on.
4. Test backups regularly.
5. Keep encryption on (default).
6. Set up CloudWatch alarms for key metrics.

## Limitations

* Maximum 64 TB storage.
* Maximum 40,000 IOPS (GP3).
* No automatic cross-region failover.
* Read replicas have replication lag.
* Maintenance windows cause brief downtime.

## Next Steps

<CardGroup cols={2}>
  <Card title="RDS Free Tier" icon="piggy-bank" href="/resources/database/rds-freetier">
    Run a free-tier-eligible PostgreSQL instance during your first 12 months.
  </Card>

  <Card title="RDS Aurora" icon="layer-group" href="/resources/database/rds-aurora">
    Scale to an Aurora cluster with serverless and global options.
  </Card>

  <Card title="Storage Factory" icon="diagram-project" href="/patterns/storage-factory">
    Provision databases and storage through the Fjall factory pattern.
  </Card>

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