Skip to main content

RDS

The RDS construct is a higher level CDK construct that makes it easy to create an RDS Serverless Cluster. It uses the following defaults:

Migrations​

The RDS construct uses Kysely to run and manage schema migrations. The migrations prop should point to the folder where your migration files are.

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
migrations: "path/to/migration/scripts",
});

On sst deploy, all migrations that have not yet been run will be run as a part of the deploy process. The migrations are executed in alphabetical order by their name.

On sst dev, migrations are not automatically run. You can manually run them via the SST Console.

note

New migrations must always have a name that comes alphabetically after the last executed migration.

Migration files should have the following format.

async function up(db) {
// Migration code
}

async function down(db) {
// Migration code
}

module.exports = { up, down };

Read more about writing migrations over on the Kysely docs.

Migrations with PostgreSQL​

async function up(db) {
await db.schema
.createTable("person")
.addColumn("id", "serial", (col) => col.primaryKey())
.addColumn("first_name", "varchar", (col) => col.notNull())
.addColumn("last_name", "varchar")
.addColumn("gender", "varchar(50)", (col) => col.notNull())
.execute();
}

async function down(db) {
await db.schema.dropTable("person").execute();
}

module.exports = { up, down };

Migrations with MySQL​

async function up(db) {
await db.schema
.createTable("person")
.addColumn("id", "integer", (col) => col.autoIncrement().primaryKey())
.addColumn("first_name", "varchar(255)", (col) => col.notNull())
.addColumn("last_name", "varchar(255)")
.addColumn("gender", "varchar(50)", (col) => col.notNull())
.execute();
}

async function down(db) {
await db.schema.dropTable("person").execute();
}

module.exports = { up, down };

Auto-scaling​

RDS automatically scales the cluster size based on CPU utilization, connections, and available memory. An RDS with the MySQL engine can scale from 1 to 256 ACU (Aurora capacity unit). And an RDS with the PostgreSQL engine can scale from 2 to 384 ACU. You can specify the minimum and maximum range for the cluster. The default minimum and maximum capacity are 2 and 16 ACU.

You can also choose to pause your RDS cluster after a given amount of time with no activity. When the cluster is paused, you are charged only for the storage. If database connections are requested when a cluster is paused, the cluster automatically resumes. By default, the cluster auto-pauses after 5 minutes of inactivity.

For dev stages, it makes sense to pick a low capacity and auto-pause time. And disable it for production stages.

const prodConfig = {
autoPause: false,
minCapacity: "ACU_8",
maxCapacity: "ACU_64",
};
const devConfig = {
autoPause: true,
minCapacity: "ACU_2",
maxCapacity: "ACU_2",
};

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
scaling: app.stage === "prod" ? prodConfig : devConfig,
});

Read more over on the RDS docs.

Examples​

Using the minimal config​

import { RDS } from "sst/constructs";

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "my_database",
});

Configuring the RDS cluster​

You can configure the internally created CDK ServerlessCluster instance.

import * as cdk from "aws-cdk-lib";

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
cdk: {
cluster: {
backupRetention: cdk.Duration.days(7),
},
},
});

Advanced examples​

Import existing RDS Serverless v1 cluster​

import * as rds from "aws-cdk-lib/aws-rds";
import * as secretsManager from "aws-cdk-lib/aws-secretsmanager";

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
cdk: {
cluster: rds.ServerlessCluster.fromServerlessClusterAttributes(
stack,
"ICluster",
{
clusterIdentifier: "my-existing-cluster",
}
),
secret: secretsManager.Secret.fromSecretAttributes(stack, "ISecret", {
secretPartialArn:
"arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret",
}),
},
});

Note that migrations are support for imported cluster. In order for migrations to work, make sure engine and defaultDatabaseName match the configuration of the imported cluster. You also need to import the secret credentials used by the cluster from the Secrets Manager.

Using existing VPC​

The RDS construct automatically creates a VPC to deploy the cluster. This VPC contains only PRIVATE and ISOLATED subnets, without NAT Gateways.

note

Since we are using the Data API, you don't need to deploy your Lambda functions into the RDS's VPC.

Yo can override the internally created VPC instance.

import * as ec2 from "aws-cdk-lib/aws-ec2";

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
cdk: {
cluster: {
vpc: ec2.Vpc.fromLookup(stack, "VPC", {
vpcId: "vpc-xxxxxxxxxx",
}),
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE,
},
},
},
});

Constructor​

new RDS(scope, id, props)

Parameters

RDSProps​

defaultDatabaseName​

Type : string

Name of a database which is automatically created inside the cluster.

engine​

Type : "mysql5.6" | "mysql5.7" | "mysql8.0" | "postgresql11.13" | "postgresql11.16" | "postgresql13.12" | "postgresql13.9" | "postgresql14.10" | "postgresql15.5" | "postgresql16.1"

Database engine of the cluster. Cannot be changed once set.

migrations?​

Type : string

Path to the directory that contains the migration scripts. The RDS construct uses Kysely to run and manage schema migrations. The migrations prop should point to the folder where your migration files are.

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
migrations: "path/to/migration/scripts",
});

scaling?​

Type :

scaling.autoPause?​

Type : number | boolean

Default : true

The time before the cluster is paused.

Pass in true to pause after 5 minutes of inactive. And pass in false to disable pausing.

Or pass in the number of minutes to wait before the cluster is paused.

new RDS(stack, "Database", {
scaling: {
autoPause: props.app.stage !== "prod"
}
})

scaling.maxCapacity?​

Type : "ACU_1" | "ACU_2" | "ACU_4" | "ACU_8" | "ACU_16" | "ACU_32" | "ACU_64" | "ACU_128" | "ACU_192" | "ACU_256" | "ACU_384"

Default : "ACU_16"

The maximum capacity for the cluster.

scaling.minCapacity?​

Type : "ACU_1" | "ACU_2" | "ACU_4" | "ACU_8" | "ACU_16" | "ACU_32" | "ACU_64" | "ACU_128" | "ACU_192" | "ACU_256" | "ACU_384"

Default : "ACU_2"

The minimum capacity for the cluster.

types?​

Type : string | RDSTypes

Path to place generated typescript types after running migrations

new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
migrations: "path/to/migration/scripts",
types: "backend/core/sql/types.ts",
});
new RDS(stack, "Database", {
engine: "postgresql11.13",
defaultDatabaseName: "acme",
migrations: "path/to/migration/scripts",
types: {
path: "backend/core/sql/types.ts",
camelCase: true
}
});

cdk?​

Type :

cdk.cluster?​

Type : IServerlessCluster | RDSCdkServerlessClusterProps

Configure the internallly created RDS cluster.

new RDS(stack, "Database", {
cdk: {
cluster: {
clusterIdentifier: "my-cluster",
}
},
});

Alternatively, you can import an existing RDS Serverless v1 Cluster in your AWS account.

new RDS(stack, "Database", {
cdk: {
cluster: rds.ServerlessCluster.fromServerlessClusterAttributes(stack, "ICluster", {
clusterIdentifier: "my-cluster",
}),
secret: secretsManager.Secret.fromSecretAttributes(stack, "ISecret", {
secretPartialArn: "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret",
}),
},
});

cdk.id?​

Type : string

Allows you to override default id for this construct.

cdk.secret?​

Type : ISecret

Required when importing existing RDS Serverless v1 Cluster.

Properties​

An instance of RDS has the following properties.

clusterArn​

Type : string

The ARN of the internally created RDS Serverless Cluster.

clusterEndpoint​

Type : Endpoint

The ARN of the internally created RDS Serverless Cluster.

clusterIdentifier​

Type : string

The ARN of the internally created RDS Serverless Cluster.

defaultDatabaseName​

Type : string

The default database name of the RDS Serverless Cluster.

id​

Type : string

migratorFunction?​

Type : Function

The ARN of the internally created CDK ServerlessCluster instance.

secretArn​

Type : string

The ARN of the internally created Secrets Manager Secret.

cdk​

Type :

cdk.cluster​

Type : ServerlessCluster

The ARN of the internally created CDK ServerlessCluster instance.

Methods​

An instance of RDS has the following methods.

runMigrations​

runMigrations(migrations, database)

Parameters

  • migrations string
  • database string

RDSTypes​

camelCase?​

Type : boolean

path​

Type : string

RDSCdkServerlessClusterProps​

vpc?​

Type : IVpc