The most surprising thing about PlanetScale’s schema diff is that it doesn’t just show you what will change, but also what could change, and even what shouldn’t change.
Let’s see it in action. Imagine you have a users table.
-- Original schema
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
);
Now, you want to add a bio column and make username case-insensitive. In a typical database, you’d just run ALTER TABLE users ADD COLUMN bio TEXT; and ALTER TABLE users MODIFY COLUMN username varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;.
But in PlanetScale, you’d create a new branch and make these changes there.
-- Schema on the new branch
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`email` varchar(255) NOT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`bio` text,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
);
When you go to create a schema diff (a "Product Change" in PlanetScale terminology), it visualizes this:
Additions:
users.bio(TEXT)
Changes:
users.username(VARCHAR(255)) - Changed collation fromutf8mb4_0900_ai_citoutf8mb4_general_ci.
This is where it gets interesting. PlanetScale’s diff goes beyond just the explicit changes. It flags potential issues and provides context. For instance, it might tell you:
- "This change requires a table rewrite." For adding a column, especially on very large tables, PlanetScale can perform this with zero downtime by creating a new table in the background, copying data, and then swapping it.
- "This change is potentially risky for production." For example, if you were dropping a column that’s heavily indexed or referenced by foreign keys, it would warn you.
- "This change could be optimized." It might suggest, for example, that if you’re adding a nullable column, it’s usually faster than adding a non-nullable one without a default.
The mental model here is that PlanetScale treats your database schema like code. You branch, you commit changes (by creating a Product Change), and you review them before merging (deploying). The diff is your code review for the database.
The underlying mechanism for many of these "safe" schema changes, like adding a nullable column or changing character sets, relies on a technique called "online schema migration." PlanetScale creates a new version of the table with the desired schema, populates it with data from the old table concurrently, and then atomically swaps the old table for the new one. This process is carefully managed to ensure no data loss and minimal to zero downtime. For more complex changes, like adding a non-nullable column without a default, PlanetScale might require a brief write-lock during the final swap, but it will clearly indicate this in the diff.
What most people don’t realize is how granular the diff can get. It doesn’t just say "column modified." It tells you which part of the column definition changed – the data type, the nullability, the default value, the character set, the collation. This level of detail is crucial for understanding the impact of your schema changes, not just the fact that they occurred. It also means that if you accidentally changed a NOT NULL to NULL when you meant to change a default, the diff will highlight that specific alteration, not just a generic "column changed."
The next step after reviewing and deploying a schema diff is understanding how to handle data migrations that might accompany schema changes.