Skip to content

PlanetScale

PlanetScale gives you serverless MySQL (Vitess-backed) and managed Postgres with a branch-per-PR workflow. With alchemy you declare the database, its branches, and the credentials as resources in the same Stack as your Workers — branches fork per preview stage and tear down with it.

New here? Set up credentials first.

PlanetScale runs two engines, and alchemy models each as its own resource family:

  • Postgres — managed PostgreSQL. PostgresDatabase, PostgresBranch, and PostgresRole (a user + password with least-privilege inherited roles).
  • MySQL — Vitess-backed serverless MySQL. MySQLDatabase, MySQLBranch, and MySQLPassword (with role: "readwriter" instead of inherited roles).

Both families share the same shape — only the credential model differs.

A database owns the long-lived cluster, a branch is a cheap fork, and a role materializes a user + password. In Postgres terms:

const database = yield* Planetscale.PostgresDatabase("app-db", {
region: { slug: "us-east" },
clusterSize: "PS_10",
});
const branch = yield* Planetscale.PostgresBranch("app-branch", {
database,
isProduction: false,
});
const role = yield* Planetscale.PostgresRole("app-role", {
database,
branch,
inheritedRoles: ["postgres"],
});

Every database and branch also accepts a migrationsDir of .sql files applied in order on each deploy — see Migrations for ordering, hashing, and the Drizzle pairing.

The role’s origin output (host / port / database / user / password) feeds straight into Cloudflare Hyperdrive for edge-pooled connections:

const hyperdrive = yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", {
origin: role.origin,
});

The guides that take this to production live under Cloudflare — each covers PlanetScale directly, Postgres and MySQL alike: