Reverting schema changes in PlanetScale is surprisingly more about understanding the underlying Git-like branching and merging than a simple "undo" button.
Let’s see it in action. Imagine you’ve made a change in your main branch, like adding a last_login timestamp to your users table.
-- In your schema file for branch 'main'
ALTER TABLE users ADD COLUMN last_login TIMESTAMP NULL DEFAULT NULL;
You then deploy this to production. Everything seems fine for a day, but then you realize last_login should have been NOT NULL and have a default value. Oops.
In a traditional database, you’d be stuck running ALTER TABLE again, potentially locking the table and causing downtime. In PlanetScale, you’d navigate to your main branch’s deploy requests. You’d see the request that added last_login. Instead of trying to modify it, you’d create a new branch from the commit before that ALTER TABLE statement.
Let’s say that commit was abcdef1. You’d branch off abcdef1 and name your new branch fix-last-login. Now, in this fix-last-login branch, you’d modify your schema to correct the last_login column.
-- In your schema file for branch 'fix-last-login'
ALTER TABLE users
MODIFY COLUMN last_login TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
This new schema change is now isolated in your fix-last-login branch. You then create a deploy request from fix-last-login to main. This deploy request will only contain the ALTER TABLE ... MODIFY COLUMN statement. When you merge this deploy request into main, PlanetScale will intelligently perform the MODIFY COLUMN operation.
The core problem PlanetScale solves here is the destructive nature of traditional schema migrations. Each ALTER TABLE command in most systems is a one-way street, often involving table rewrites or significant locking. PlanetScale’s model treats schema changes like code commits. When you "revert" a change, you’re not truly undoing a past operation on the production database. Instead, you’re creating a new state that effectively corrects the previous one, applied atomically and with zero downtime.
The system works by maintaining a history of your schema as a series of commits. Each branch represents a point in that history, and deploy requests are essentially merge operations between branches. When you create a fix-last-login branch from an older commit, you’re creating a new line of development that diverges from the current main branch at that specific historical point. The subsequent merge then applies the difference between your fix-last-login branch and the main branch at the time of the merge. If main has evolved since you branched, PlanetScale will show you a diff and potentially require you to resolve conflicts, just like Git.
This Git-like approach applies to more than just "reverts." If you want to roll back a problematic deployment entirely, you create a new branch from the commit before the problematic one, and then merge that branch into main. The deploy request will contain a schema change that effectively undoes the previous one. For example, if you added a column and want to remove it, you’d branch from before the ADD COLUMN statement, then in your new branch, DROP COLUMN. Merging this into main would then drop the column.
The most surprising mechanical detail is how PlanetScale handles DROP COLUMN operations. Even if you’ve dropped a column in a branch and merged it, PlanetScale keeps the data for a period (configurable via retention policies, often 7 days by default). If you then realize you accidentally dropped it and need to get it back, you can branch from before the DROP COLUMN statement, recreate the column (without the DROP COLUMN in the new branch’s schema), and merge it back. The data is still there, ready to be reattached.
The next concept you’ll grapple with is schema validation and conflict resolution during merges.