www/src/content/docs/docs/start/aws/drizzle.mdx
You can use SST to deploy an Amazon Postgres RDS database and set up Drizzle ORM and Drizzle Kit to manage it.
:::tip[View source] You can view the source of this example in our repo. :::
Before you get started, make sure to configure your AWS credentials.
We also have a few other Drizzle and Postgres examples that you can refer to.
Let's start by creating a Node.js app.
mkdir aws-drizzle && cd aws-drizzle
npm init -y
Now let's initialize SST in our app.
npx sst@latest init
npm install
Select the defaults and pick AWS. This'll create a sst.config.ts file in your project root.
Add Drizzle to your project. We're also adding the pg client that Drizzle will use.
npm install pg @types/pg drizzle-orm drizzle-kit
Drizzle ORM is what will be used to query our database, while Drizzle Kit will allow us to run migrations. It also comes with Drizzle Studio, a query browser.
Let's add the following to the scripts in the package.json.
"scripts": {
"db": "sst shell drizzle-kit"
},
The sst shell CLI will pass the credentials to Drizzle Kit and allow it to connect to your database.
Let's also update our tsconfig.json.
{
"compilerOptions": {
"strict": true
}
}
Let's add a Postgres database using Amazon RDS. This needs a VPC. Update your sst.config.ts.
async run() {
const vpc = new sst.aws.Vpc("MyVpc", { bastion: true, nat: "ec2" });
const rds = new sst.aws.Postgres("MyPostgres", { vpc, proxy: true });
},
The proxy option configures an RDS Proxy behind the scenes making it ideal for serverless applications.
:::tip The RDS Proxy allows serverless environments to reliably connect to RDS. :::
While the bastion option will let us connect to the VPC from our local machine. We also need the NAT gateway for this example since we'll be using a Lambda function, and this allows a Lambda function that's in a VPC to access the internet.
When you run SST in dev it can start other dev processes for you. In this case we want to start Drizzle Studio. Add this below the Postgres component.
new sst.x.DevCommand("Studio", {
link: [rds],
dev: {
command: "npx drizzle-kit studio",
},
});
This will run the given command in dev.
We'll use a Lambda function as an API to query our database. Add the following to your sst.config.ts below the database config.
new sst.aws.Function("MyApi", {
vpc,
url: true,
link: [rds],
handler: "src/api.handler",
});
We are linking our database to the API.
Since our database cluster is in a VPC, we'll need a tunnel to connect to it from our local machine.
sudo npx sst tunnel install
This needs sudo to create a network interface on your machine. You'll only need to do this once on your machine.
Start your app in dev mode. This runs your functions Live.
npx sst dev
It'll take a few minutes to create your database. Once complete, you'll see this.
✓ Complete
MyApi: https://ouu5vovpxllyn5b6ot2nn6vdsa0hvcuj.lambda-url.us-east-1.on.aws
You'll see Drizzle Studio started in a tab called Studio. And a tunnel in the Tunnel tab.
Let's define our Drizzle config. Add a drizzle.config.ts in your project root with this.
import { Resource } from "sst";
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
// Pick up all our schema files
schema: ["./src/**/*.sql.ts"],
out: "./migrations",
dbCredentials: {
host: Resource.MyPostgres.host,
port: Resource.MyPostgres.port,
user: Resource.MyPostgres.username,
password: Resource.MyPostgres.password,
database: Resource.MyPostgres.database,
},
});
Here we are telling Drizzle that we'll be specifying your database schema in .sql.ts files in our src/ directory.
:::tip
SST allows us to automatically access our database with Resource.MyPostgres.*.
:::
We are going to create a simple database to store some todos. Create a new file in src/todo.sql.ts with the following.
import { text, serial, pgTable } from "drizzle-orm/pg-core";
export const todo = pgTable("todo", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
description: text("description"),
});
We can use this to generate a migration.
npm run db generate
This in turn runs sst shell drizzle-kit generate and creates a new migration in the migrations/ directory.
Now we can apply our migration using.
npm run db migrate
This should create our new schema.
:::tip You need a tunnel to connect to your database. :::
This needs the tunnel to connect to the database. So you should have sst dev in a separate terminal.
npx sst tunnel
Alternatively, you can just run the tunnel using the above command.
To see our schema in action we can open the Drizzle Studio. Head over to the Studio tab in your sst dev session and go to the link.
Or head over to https://local.drizzle.studio in your browser.
To use Drizzle ORM to query our database, create a new src/drizzle.ts config file with the following.
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { Resource } from "sst";
import * as schema from "./todo.sql";
const pool = new Pool({
host: Resource.MyPostgres.host,
port: Resource.MyPostgres.port,
user: Resource.MyPostgres.username,
password: Resource.MyPostgres.password,
database: Resource.MyPostgres.database,
});
export const db = drizzle(pool, { schema });
Now we can use that in the API. Create our API handler in src/api.ts.
import { db } from "./drizzle";
import { todo } from "./todo.sql";
import { APIGatewayProxyEventV2 } from "aws-lambda";
export const handler = async (evt: APIGatewayProxyEventV2) => {
if (evt.requestContext.http.method === "GET") {
const result = await db.select().from(todo).execute();
return {
statusCode: 200,
body: JSON.stringify(result, null, 2),
};
}
if (evt.requestContext.http.method === "POST") {
const result = await db
.insert(todo)
.values({ title: "Todo", description: crypto.randomUUID() })
.returning()
.execute();
return {
statusCode: 200,
body: JSON.stringify(result),
};
}
};
For POST requests we create a new todo and for GET requests we simply print out all our todos.
To test our app, make a POST request to our API.
curl -X POST https://ouu5vovpxllyn5b6ot2nn6vdsa0hvcuj.lambda-url.us-east-1.on.aws
Now if you head over to https://ouu5vovpxllyn5b6ot2nn6vdsa0hvcuj.lambda-url.us-east-1.on.aws in your browser, you'll see that a todo has been added.
You should see this in the Drizzle Studio as well.
Finally, let's deploy your app.
npx sst deploy --stage production
You can use any stage name here but it's good to create a new stage for production.
As a next step, you can setup the SST Console to git push to deploy your app and monitor it for any issues.
You can create a free account and connect it to your AWS account.