| 1 | --- |
| 2 | title: PlanetScale |
| 3 | description: Serverless MySQL (Vitess) and Postgres with database branching — databases, branches, and credentials as Stack resources. |
| 4 | --- |
| 5 | |
| 6 | PlanetScale gives you serverless MySQL (Vitess-backed) and managed |
| 7 | Postgres with a branch-per-PR workflow. With alchemy you declare the |
| 8 | database, its branches, and the credentials as resources in the same |
| 9 | Stack as your Workers — branches fork per preview stage and tear |
| 10 | down with it. |
| 11 | |
| 12 | New here? [Set up credentials](/planetscale/setup) first. |
| 13 | |
| 14 | ## Choose an engine |
| 15 | |
| 16 | PlanetScale runs two engines, and alchemy models each as its own |
| 17 | resource family: |
| 18 | |
| 19 | - [Postgres](/planetscale/data/postgres) — managed PostgreSQL. |
| 20 | `PostgresDatabase`, `PostgresBranch`, and `PostgresRole` (a user + |
| 21 | password with least-privilege inherited roles). |
| 22 | - [MySQL](/planetscale/data/mysql) — Vitess-backed serverless MySQL. |
| 23 | `MySQLDatabase`, `MySQLBranch`, and `MySQLPassword` (with |
| 24 | `role: "readwriter"` instead of inherited roles). |
| 25 | |
| 26 | Both families share the same shape — only the credential model |
| 27 | differs. |
| 28 | |
| 29 | ## Resources |
| 30 | |
| 31 | A database owns the long-lived cluster, a branch is a cheap fork, |
| 32 | and a role materializes a user + password. In Postgres terms: |
| 33 | |
| 34 | ```typescript |
| 35 | const database = yield* Planetscale.PostgresDatabase("app-db", { |
| 36 | region: { slug: "us-east" }, |
| 37 | clusterSize: "PS_10", |
| 38 | }); |
| 39 | |
| 40 | const branch = yield* Planetscale.PostgresBranch("app-branch", { |
| 41 | database, |
| 42 | isProduction: false, |
| 43 | }); |
| 44 | |
| 45 | const role = yield* Planetscale.PostgresRole("app-role", { |
| 46 | database, |
| 47 | branch, |
| 48 | inheritedRoles: ["postgres"], |
| 49 | }); |
| 50 | ``` |
| 51 | |
| 52 | Every database and branch also accepts a `migrations` folder of `.sql` |
| 53 | files applied in order on each deploy — see |
| 54 | [Migrations](/planetscale/data/migrations) for ordering, hashing, and the |
| 55 | Drizzle pairing. |
| 56 | |
| 57 | ## The PlanetScale path |
| 58 | |
| 59 | The role's `origin` output (host / port / database / user / password) |
| 60 | feeds straight into Cloudflare Hyperdrive for edge-pooled |
| 61 | connections: |
| 62 | |
| 63 | ```typescript |
| 64 | const hyperdrive = yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", { |
| 65 | origin: role.origin, |
| 66 | }); |
| 67 | ``` |
| 68 | |
| 69 | The guides that take this to production live under Cloudflare — |
| 70 | each covers PlanetScale directly, Postgres and MySQL alike: |
| 71 | |
| 72 | - [Hyperdrive](/cloudflare/data/hyperdrive) — provision the database, |
| 73 | front it with Hyperdrive, and bind the connection into a Worker. |
| 74 | - [Add Drizzle ORM](/cloudflare/data/drizzle) — schema as a |
| 75 | resource, migrations generated and applied on every deploy. |
| 76 | - [Shared database across stages](/cloudflare/data/shared-database) |
| 77 | and [branch from a shared database](/cloudflare/data/branch-from-shared-database) |
| 78 | — branch-per-PR preview environments off one long-lived database. |
| 79 | |
| 80 | ## Reference |
| 81 | |
| 82 | - Postgres: |
| 83 | [PostgresDatabase](/providers/planetscale/postgres/postgresdatabase) · |
| 84 | [PostgresBranch](/providers/planetscale/postgres/postgresbranch) · |
| 85 | [PostgresRole](/providers/planetscale/postgres/postgresrole) · |
| 86 | [PostgresDefaultRole](/providers/planetscale/postgres/postgresdefaultrole) |
| 87 | - MySQL: |
| 88 | [MySQLDatabase](/providers/planetscale/mysql/mysqldatabase) · |
| 89 | [MySQLBranch](/providers/planetscale/mysql/mysqlbranch) · |
| 90 | [MySQLPassword](/providers/planetscale/mysql/mysqlpassword) |