Serverless MySQL on Vitess — the same database Slack, GitHub, and YouTube run on. Non-blocking schema changes through deploy requests. Sign up, create a database, connect.
PlanetScale removed its free tier in April 2024; pricing now starts at $39/mo. Real reason to pick PlanetScale today is the team-scale-ready architecture, not the bargain.
Sign up at planetscale.com ↗. Pick a plan (no free tier; PlanetScale pricing ↗).
Create database:
Provisioning takes ~1–2 minutes.
Database dashboard → Connect. Pick your language; PlanetScale generates the connection string with the right format.
DATABASE_URL=mysql://<user>:<password>@<host>/<db>?ssl={"rejectUnauthorized":true}
SSL is required (no plaintext connections). Most MySQL clients handle this automatically with the right URL.
Save to env. Credentials are scoped per-branch (more on that below) and can be rotated from the dashboard.
Any MySQL library works. Common patterns:
Node + mysql2:
npm install mysql2
import mysql from "mysql2/promise";
const pool = mysql.createPool({ uri: process.env.DATABASE_URL });
const [rows] = await pool.query("SELECT * FROM users WHERE id = ?", [123]);
Serverless / edge (PlanetScale's HTTP driver):
npm install @planetscale/database
import { connect } from "@planetscale/database";
const conn = connect({ url: process.env.DATABASE_URL });
const results = await conn.execute("SELECT * FROM users WHERE id = ?", [123]);
The HTTP driver works in Cloudflare Workers, Vercel Edge Functions, AWS Lambda — places traditional TCP MySQL clients can't run. Serverless driver docs ↗.
PlanetScale Console → Console (Beta) tab → SQL editor. Or use any MySQL client (e.g., mysql CLI, TablePlus, DBeaver) against the connection string.
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ORMs: Drizzle, Prisma, Kysely all have MySQL adapters that work transparently with PlanetScale.
PlanetScale invented database branching. The model:
Practical workflow:
pscale branch create my-db add-users-table
pscale deploy-request create my-db add-users-table
# Review in the dashboard, then:
pscale deploy-request deploy my-db <number>
brew install planetscale/tap/pscale # macOS
# Or download from https://github.com/planetscale/cli/releases for Windows/Linux
pscale auth login
The CLI lets you connect to PlanetScale through a local proxy:
pscale connect my-db main --port 3306
Now your local mysql -h 127.0.0.1 connects to production (read-only by default; toggle to allow writes). Great for ad-hoc queries without exposing credentials in your terminal history.
This is the most surprising PlanetScale gotcha: foreign key constraints are disabled by default because Vitess shards across nodes where cross-shard FK constraints don't work.
You can enable FK constraints for non-sharded databases via dashboard → Settings → Foreign key constraints. But the official recommendation is to enforce relational integrity in your application code (or via the ORM) instead.
If foreign keys are a hard requirement for you, Neon is friendlier.
Dashboard → Insights. Shows:
Each slow query is clickable — see the exact text, average and p99 latency, suggested indexes (if applicable). Much friendlier than digging through MySQL's slow query log manually.
Automatic daily backups, retained per plan. Manual on-demand backups via dashboard or CLI:
pscale backup create my-db main
Restore is to a new branch (not in-place over main), so you can validate before swapping.
CREATE INDEX CONCURRENTLY — but online schema changes handle that automatically. For most app code, you won't hit these; for power-user MySQL patterns, check the compatibility matrix ↗.