PlanetScale Basics Cheat Sheet
Introduces PlanetScale's Git-style branching workflow for MySQL schema changes, deploy requests, the pscale CLI, and connecting from application code.
pscale CLI Setup
Authenticate, create a database, and open a branch shell.
# Install the pscale CLI, then authenticatebrew install planetscale/tap/pscalepscale auth login# Create a database (its default branch is called "main")pscale database create my_app --region us-east# Open an interactive MySQL shell against a branchpscale shell my_app main
Branch & Deploy Request Workflow
Make schema changes on a branch, then merge them into main via a deploy request.
# Create a development branch to make schema changes onpscale branch create my_app add-orders-table# Open a secure local proxy to the branch and connect any MySQL clientpscale connect my_app add-orders-table --port 3309# In another terminal: run DDL against the branchmysql -h 127.0.0.1 -P 3309 -u root <<'SQL'ALTER TABLE orders ADD COLUMN discount_code VARCHAR(20);SQL# Open a deploy request (like a pull request for schema)pscale deploy-request create my_app add-orders-table# Review it, then deploy — applies the diff to main with minimal lockingpscale deploy-request deploy my_app <deploy-request-number>
Connecting from Node.js
Connect to a PlanetScale branch from application code with mysql2 (TLS required).
import mysql from 'mysql2/promise'const connection = await mysql.createConnection({ host: process.env.DATABASE_HOST, // e.g. aws.connect.psdb.cloud user: process.env.DATABASE_USERNAME, password: process.env.DATABASE_PASSWORD, database: 'my_app', ssl: { rejectUnauthorized: true }, // PlanetScale requires TLS})const [rows] = await connection.execute( 'SELECT * FROM orders WHERE customer_id = ?', [customerId])
Core Concepts
Terminology and behavior specific to PlanetScale's workflow.
- Branching workflow- Every schema change happens on a database branch (like a Git branch); production workflows never run DDL directly against main.
- Deploy requests- PlanetScale's equivalent of a pull request for schema — diffs the branch against the target branch and applies changes using online, non-blocking DDL.
- Built on Vitess- PlanetScale runs on Vitess, the MySQL sharding middleware originally built at YouTube, giving it horizontal scalability beyond a single MySQL instance.
- Non-blocking schema changes- Deploy requests use online schema-change tooling so ALTER TABLE on large tables doesn't hold long locks against production writes.
- Connection via secure proxy- pscale connect opens a local proxy so you can use any standard MySQL client without exposing raw database credentials.
- Safe migrations- When enabled on a branch, PlanetScale can block schema changes that aren't backward-compatible, such as dropping a column the app still reads.
- MySQL-compatible- Standard MySQL client libraries and the MySQL wire protocol work unmodified; PlanetScale is not a fork with a different query language.
Safe Migrations & Reverting a Deploy Request
Enable backward-compatibility checks on a branch and roll back a bad deploy.
# Turn on safe migrations for a branch so backward-incompatible changes# (e.g. dropping a column the app still reads) are flagged before deploypscale branch safe-migrations enable my_app add-orders-table# List deploy requests and their statepscale deploy-request list my_app# If a deployed change causes problems, revert it (creates a new deploy request# that applies the inverse diff, rather than a destructive rollback)pscale deploy-request revert my_app <deploy-request-number>
Prisma with Emulated Foreign Keys
Configure Prisma to emulate relational integrity at the query-engine level for sharded branches.
datasource db { provider = "mysql" url = env("DATABASE_URL") relationMode = "prisma" // enforce relations in the query engine, not DB-level FKs}model Order { id String @id @default(cuid()) customerId String customer Customer @relation(fields: [customerId], references: [id]) @@index([customerId]) // required manually when relationMode = "prisma"}model Customer { id String @id @default(cuid()) orders Order[]}
Query Insights & Automatic Boost
Inspect slow queries from the CLI and enable index-backed read replicas for hot tables.
# Show recent slow/normalized query stats captured by Insightspscale database show my_app --region us-east# Boost accelerates specific index lookups by materializing them onto# dedicated read replicas; enable it per-branch for read-heavy tablespscale boost enable my_app main# Check current branch resource usage / row counts before scaling planspscale database usage my_app
Backups & Restoring a Branch
Create a backup on demand and spin up a new branch from it for point-in-time recovery.
# Take an on-demand backup of a branchpscale backup create my_app main --name pre-migration-snapshot# List backups available to restore frompscale backup list my_app main# Create a new branch from a backup instead of from HEADpscale branch create my_app recovery-branch --backup pre-migration-snapshot
Vitess Internals & Scaling Concepts
Terminology that matters once a database needs to scale beyond a single MySQL instance.
- Vindexes- Vitess's sharding key mechanism; defines how a sharded keyspace routes rows to physical shards based on a column's hashed or lookup value.
- Keyspace- A logical database in Vitess terms, which may map to one unsharded MySQL instance or be split across many physical shards.
- VTGate / VTTablet- VTGate is the stateless query router clients connect to; VTTablet sits in front of each MySQL instance and manages replication and query execution.
- Non-blocking schema changes- Deploy requests use an online DDL mechanism (gh-ost-style shadow table + swap) so large ALTER TABLE statements don't hold long write locks.
- Production branch protections- The default `main` branch can be marked protected so nobody can run DDL directly against it — all changes must flow through a deploy request.
- Cluster sizing- Paid plans let you pick a dedicated cluster size (replicas + read-only nodes) per branch, decoupling branch compute from the free shared tier.
Keep each branch's schema change small and focused — large, multi-table deploy requests are harder to review, and PlanetScale's online schema-change process takes longer and holds resources longer the bigger the diff.