Register your interest: Tag @Cody, get an agent
BlogEngineering

PlanetScale and CodeWords: schema changes without locking

Branches and deploy requests, the foreign key question, Vitess sharding behind a MySQL interface, and what automating against a database with a review process actually looks like.

Aymeric ZhuoAymeric Zhuo11 min read

Summarize with AI

PlanetScale and CodeWords: schema changes without locking
On this page

PlanetScale's central idea is that a schema change should go through a review process like code, and should apply without locking the table. Branches hold schema changes, a deploy request carries them to production, and the change is applied online.

For automation that changes two things. Migrations stop being a deployment-time risk and become a reviewable artefact, and the platform is Vitess underneath, which imposes a few rules that ordinary MySQL does not.

What we'll cover

Branches and deploy requests

A development branch holds schema changes and is where migrations are applied first.

A deploy request carries those changes to production, with a diff showing exactly what will happen. This is the artefact worth putting in front of a person.

The platform checks for problems before deploying, catching a class of changes that would be dangerous on a large table.

Deployment is online. The change applies without locking the table, which removes the maintenance window that schema changes traditionally need.

Reverting is supported within a window after deployment, which is the safety net most migration processes lack entirely.

For automation, the useful pattern is: create a branch, apply the migration, open a deploy request, report the diff and any warnings to the team, and let a person approve production. The automation removes the mechanics; the approval stays where it belongs.

Vitess, and what it changes

The interface is MySQL and the engine is Vitess, which imposes constraints worth knowing before designing anything.

Foreign key support has historically been limited, and the conventional advice on PlanetScale is to enforce referential integrity in the application. Check the current behaviour for your deployment rather than assuming either way, since this has changed over time.

Queries that would fan out across shards are constrained, so a query pattern that works on a single MySQL instance may behave differently at scale.

Some MySQL features are unavailable, and the list is specific rather than sweeping — confirm the ones you rely on.

Online schema change is the norm, which means schema changes that would be risky elsewhere are routine here.

Connection behaviour differs from a single MySQL server, which matters for anything holding connections.

If referential integrity is enforced in the application rather than the database, orphan detection becomes an automation worth building rather than something the database guarantees.

What PlanetScale reaches

The MySQL wire protocol, so ordinary MySQL clients and query patterns apply.

Branches can be created, listed, and deleted through the API.

Deploy requests can be created, read, approved, and deployed programmatically, which is what makes migration automation possible.

Schema diffs can be retrieved for a branch or a deploy request, which is the readable artefact for review.

Insights report query performance — which queries are slow, which are frequent, and which consume the most time in aggregate.

Backups and restores can be managed, including restoring into a branch.

Organisation and database management for provisioning.

A serverless driver over HTTP for environments where persistent connections are impractical.

Connecting it to CodeWords

CodeWords connects to more than 3,000 integrations, and the connection is made once and reused.

  1. Open CodeWords and start a new automation.
  2. Describe what should happen in plain language to Cody, the automation builder: which database or branch, and what should happen.
  3. Authorize the connection with a service token for management operations and database credentials scoped to a branch for anything querying.
  4. Describe the exceptions: a deploy request with warnings, a branch that already exists, a query that times out.
  5. Test against a development branch before anything touches production.

You describe the outcome; Cody builds it, connects it, and deploys it. The free plan covers light use, with Pro at $39 per month and Business at $100 per month as usage grows; details are on the pricing page.

Seven automations worth building

Deploy request review summaries. When one is opened, post the schema diff and any warnings in readable form to the team, so the review happens where the team is rather than in a tab nobody opened.

Branch lifecycle management. Development branches created per pull request and deleted when it closes, with a weekly sweep for orphans.

Referential integrity checking. Orphaned rows across the relationships your application enforces, reported rather than deleted. Essential where the database is not enforcing them.

Slow query reporting from Insights. Which queries consume the most time in aggregate, which is usually a frequent cheap query rather than the obviously slow one.

Data quality checks. Duplicates by business key, values outside expected ranges, and records in impossible states, run read-only against a branch.

Operational reporting. The query somebody runs weekly, delivered before they ask.

Migration rehearsal reporting. How long a deployment took and whether it produced warnings, recorded so the pattern across migrations is visible.

Insights, which tell you what is actually slow

Query performance data is available without any instrumentation, and most teams never look at it.

Rank by total time, not by worst case. A query taking twenty milliseconds and running a million times a day costs far more than one taking two seconds and running hourly.

Look for the query that got slower, rather than the one that is slowest. A query whose time doubled last week is a regression; one that has always been slow is a known cost.

Correlate with deployments. A query appearing or changing shape after a release is usually an unintended consequence of a code change.

Report by trend, weekly, to whoever owns the code. A ranked list with the change since last week is actionable; a static top ten is a wallpaper.

Watch rows examined against rows returned. A large ratio means a missing index, and it is the clearest signal available.

Connections and pooling

Connection limits apply and depend on your plan, so bursty automation needs care.

Use a pooler or reuse connections within a run, rather than opening one per operation.

The HTTP driver avoids the question entirely for short-lived functions and simple queries, which is often what an automation is.

Close what you open, including on error paths, which is where leaks come from.

Use branch-scoped credentials. A password for a development branch that cannot reach production is a meaningful safety property, and it is free.

Migrations that are safe to apply online

Online schema change removes the locking problem and does not remove every problem, and the difference is worth knowing.

Adding a nullable column is trivial. So is adding an index, which is the change most likely to need a maintenance window elsewhere.

Adding a non-nullable column with a default is fine; without one is not, since existing rows have nothing to put there.

Dropping a column is safe to apply and unsafe to deploy, if any running code still selects it. The database change and the application change need ordering, and the ordering is the migration's actual risk.

Renaming is two deployments, not one. Add the new, write to both, backfill, switch reads, drop the old. The single-step rename is what breaks during the window between deployments.

Backfills are separate from schema changes. A backfill over a large table should be a paced batch job, not something attached to a migration.

The check the platform performs catches the dangerous schema changes. It cannot catch a safe schema change deployed in the wrong order relative to your code, which is the failure that remains yours.

Building it so it survives

Never deploy schema changes without a person approving, however tempting the automation. The check and the diff are the value; the approval is the point.

Make writes idempotent, using insert-on-duplicate-key semantics or a conflict-safe pattern.

Paginate by key, not by offset, since offset pagination degrades as it goes deeper.

Check the branch you are connected to before writing anything, and make it impossible for a development automation to hold production credentials.

Report the outcome. Rows read and written, deploy requests opened, and branches created and removed.

Limits worth knowing about

Branch count and storage are plan-dependent, and unattended branch creation finds the limit.

Some MySQL features are unavailable under Vitess, and the specifics are worth confirming against your own query patterns.

Foreign key behaviour has changed over time, so check what your deployment does rather than relying on advice of uncertain vintage.

Deploy request checks can block a change, which is the system working and is worth surfacing clearly rather than treating as an error.

Revert windows are bounded, so the safety net is time-limited and worth knowing the length of.

What to build first

Deploy request review summaries: when a deploy request opens, post the schema diff and any warnings into the team's channel in readable form. It changes nothing about the process, it takes little building, and it moves schema review from a tab somebody has to remember to open into the place where the team already discusses changes.

Two habits make the difference. Include the warnings prominently rather than as an appendix, since those are the whole reason the platform checks. And name the tables affected in the summary line, because "adds a column to users" gets read and "schema change opened" does not.

Frequently asked questions

Can automation deploy schema changes?

It can prepare them — branch, migration, deploy request, diff and warnings posted for review — and a person should approve the production deployment. The mechanics are the tedious part; the approval is the check.

Do foreign keys work?

Behaviour here has changed over time, so check what your deployment actually supports rather than relying on older advice. Where integrity is enforced in the application rather than the database, an orphan-detection automation is worth building.

Why is my query behaving differently from plain MySQL?

Because Vitess sits underneath, and some query patterns — particularly anything that would fan out across shards — are constrained. The interface is MySQL; the engine is not a single MySQL server.

Which slow query should I fix first?

The one consuming the most total time, which is usually a fast query running very often rather than the slowest one. Insights gives you this without any instrumentation, and almost nobody looks at it.

How do I stop branches accumulating?

Delete on pull request close and sweep weekly for orphans, since a webhook will eventually be missed. Branch count and storage are plan-limited and unattended creation finds that limit.

Should automation use production credentials?

Only where it genuinely needs production. Branch-scoped credentials mean a development automation cannot reach production data at all, which is a stronger guarantee than being careful.

What happens if a deploy request is blocked?

The platform found a problem with the change, which is the system doing its job. Surface it clearly to whoever opened it rather than treating it as a failure of the automation — the message usually says exactly what is wrong.

If schema changes are online, what can still go wrong?

Ordering relative to your application. Dropping a column is safe to apply and breaks any code still selecting it, and a rename done in one step breaks during the deployment window. The platform checks the schema change; it cannot check your deployment order.

How should a large backfill run?

As a paced batch job separate from the migration, keyed so it can resume. Attaching a backfill over millions of rows to a schema change turns a routine online change into a long-running operation.

Get started today

Your first workflow is free to build.

Describe what you need. Cody handles the build, the connections, and the deployment.