PlanetScale’s zero-downtime ALTER TABLE isn’t magic; it’s a carefully orchestrated, multi-step process that leverages a MySQL feature called pt-online-schema-change or a similar underlying mechanism to avoid locking your tables during schema modifications.
Let’s see this in action. Imagine you have a users table and need to add an email_verified_at timestamp column.
-- Initial table state
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Insert some data
INSERT INTO users (username) VALUES ('alice'), ('bob');
Now, you want to add email_verified_at. A standard ALTER TABLE would lock users for the duration of the change. On a busy production system, this is a no-go. PlanetScale, however, handles it differently.
When you initiate a schema change in PlanetScale (via their UI or planetscale CLI), it doesn’t directly run ALTER TABLE on your primary database. Instead, it follows these steps:
-
Create a new table: A new table, often suffixed with a temporary name (e.g.,
users_new_xyz123), is created with the desired schema, including the newemail_verified_atcolumn. -
Copy data in the background: Data from the original
userstable is copied tousers_new_xyz123in chunks. This is the most time-consuming part, but it happens without impacting read or write operations on the original table. -
Capture ongoing changes: While data is being copied, PlanetScale uses MySQL’s binary log (binlog) to capture any
INSERT,UPDATE, orDELETEoperations that occur on the originaluserstable. -
Apply captured changes: Once the initial data copy is complete, PlanetScale applies the changes recorded in the binlog to the new
users_new_xyz123table. This ensures the new table is in sync with the current state of the original. -
Atomic rename: This is the critical zero-downtime step. PlanetScale briefly renames the original
userstable to something likeusers_old_xyz123and simultaneously renamesusers_new_xyz123tousers. This rename operation is extremely fast and atomic, causing a very brief, often imperceptible, write interruption. Reads might also see a momentary blip, but application-level retry mechanisms usually handle this without issue. -
Drop old table: After a grace period, the old
users_old_xyz123table is dropped.
The email_verified_at column is now present, and your application experienced no downtime.
Your primary levers for controlling this process are the schema definition itself and the timing of your deployments. PlanetScale’s system is designed to be robust, but understanding the underlying mechanism helps in troubleshooting or in planning for more complex scenarios. For instance, if you have very high write throughput, the "apply captured changes" step might take longer, potentially extending the overall time your schema change is "in flight."
The surprise is that the "locking" doesn’t happen on the table you’re querying. The new table is built, synchronized, and then atomically swapped in. This is very different from traditional ALTER TABLE which modifies the table in place, locking it for the duration.
The next thing you’ll likely encounter is how to handle schema changes that can’t be done online, such as dropping a column that’s currently being referenced by a foreign key constraint or changing a column’s data type in a way that requires a full table rewrite and cannot be achieved through simple row-by-row updates.