Drizzle ORM with PlanetScale
Use the portable Postgres or MySQL client with PlanetScale. This page owns database configuration; Add Drizzle ORM owns Worker deployment.
Define the schema
Section titled “Define the schema”import { defineConfig } from "drizzle-kit";
export default defineConfig({ schema: "./src/schema.ts", out: "./migrations", dialect: "postgresql",});Use the Postgres schema example with pg-core columns, or select dialect: "mysql" with the MySQL schema.
Generate and review migrations
Section titled “Generate and review migrations”bunx drizzle-kit generategit diff -- src/schema.ts migrationsgit status --shortgit add src/schema.ts drizzle.config.ts migrationsgit diff --cachedgit commit -m "Add database migration"Generate when the schema changes, then review and commit the schema, SQL, and snapshots together before deploying. The optional Drizzle.Schema resource is not required for this workflow.
Apply them on the branch
Section titled “Apply them on the branch”import * as Planetscale from "alchemy/Planetscale";import * as Effect from "effect/Effect";
export const PlanetscaleDb = Effect.gen(function* () { const database = yield* Planetscale.PostgresDatabase("app-db", { region: { slug: "us-east" }, clusterSize: "PS_10", }); const branch = yield* Planetscale.PostgresBranch("app-branch", { database, migrations: "./migrations", }); const role = yield* Planetscale.PostgresRole("app-role", { database, branch, inheritedRoles: ["postgres"], }); return { database, branch, role };});Register Planetscale.providers() in your Stack; the branch applies committed migrations transactionally and the role supplies application credentials. Postgres covers branch and role options.
Connect via origin / pooledOrigin
Section titled “Connect via origin / pooledOrigin”import * as Cloudflare from "alchemy/Cloudflare";
export const Hyperdrive = Effect.gen(function* () { const { role } = yield* PlanetscaleDb; return yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", { origin: role.origin, dev: role.pooledOrigin, caching: { disabled: true }, });});role.origin uses direct port 5432, while role.pooledOrigin uses PSBouncer on port 6432. Other runtimes can consume the redacted connectionUrl or connectionUrlPooled; the Cloudflare walkthrough continues from this Hyperdrive resource.
MySQL: generate and check in migrations
Section titled “MySQL: generate and check in migrations” dialect: "postgresql", dialect: "mysql",For Vitess, use mysql-core columns and run the same generate, review, and commit commands above. Do not reuse Postgres migration SQL on a MySQL branch.
MySQL: apply and connect
Section titled “MySQL: apply and connect”import * as Planetscale from "alchemy/Planetscale";import * as Effect from "effect/Effect";
export const PlanetscaleDb = Effect.gen(function* () { const database = yield* Planetscale.MySQLDatabase("app-db", { region: { slug: "us-east" }, clusterSize: "PS_10", }); const branch = yield* Planetscale.MySQLBranch("app-branch", { database, isProduction: false, migrations: "./migrations", }); const password = yield* Planetscale.MySQLPassword("app-password", { database, branch, role: "readwriter", }); return { database, branch, password };});MySQLPassword provides password.origin for Hyperdrive, without a pooled variant. PlanetScale migrations covers statement splitting and MySQL’s non-transactional DDL behavior.
Deploy committed files
Section titled “Deploy committed files”bun alchemy deployThe branch applies pending committed files; this configuration does not generate SQL during deployment. If drizzle-kit migrate already owns application, keep that workflow unless you deliberately choose Alchemy-managed migrations; see migration ownership.
Wire it into your runtime
Section titled “Wire it into your runtime”Follow Add Drizzle ORM for Worker bindings, or SQL databases to choose a client for another runtime. Existing Postgres and MySQL projects demonstrate connections and queries, but use the optional schema resource rather than this guide’s generation workflow.
Where next
Section titled “Where next”Read Preview branches per PR for branch provisioning, and Postgres or MySQL for database-specific behavior.