Skip to content
GitHub Discord

Drizzle migrations in CI/CD

An example on how to run Drizzle migrations as a part of your CI/CD.

Start by creating a function that runs migrations.

sst.config.ts
const migrator = new sst.aws.Function("DatabaseMigrator", {
handler: "src/migrator.handler",
link: [rds],
vpc,
copyFiles: [
{
from: "migrations",
to: "./migrations",
},
],
});

Where src/migrator.ts looks like.

src/migrator.ts
import { db } from "./drizzle";
import { migrate } from "drizzle-orm/postgres-js/migrator";
export const handler = async (event: any) => {
await migrate(db, {
migrationsFolder: "./migrations",
});
};

And we can set it up to run on every deploy.

sst.config.ts
if (!$dev){
new aws.lambda.Invocation("DatabaseMigratorInvocation", {
input: Date.now().toString(),
functionName: migrator.name,
});
}

We use the current time to make sure the function runs on every deploy.

sst.config.ts
const vpc = new sst.aws.Vpc("MyVpc", { bastion: true, nat: "ec2" });
const rds = new sst.aws.Postgres("MyPostgres", { vpc, proxy: true });
new sst.aws.Function("MyApi", {
vpc,
url: true,
link: [rds],
handler: "src/api.handler",
});
const migrator = new sst.aws.Function("DatabaseMigrator", {
handler: "src/migrator.handler",
link: [rds],
vpc,
copyFiles: [
{
from: "migrations",
to: "./migrations",
},
],
});
if (!$dev) {
new aws.lambda.Invocation("DatabaseMigratorInvocation", {
input: Date.now().toString(),
functionName: migrator.name,
});
}
new sst.x.DevCommand("Studio", {
link: [rds],
dev: {
command: "npx drizzle-kit studio",
},
});
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),
};
}
};

View the full example.