Migrating your database from Heroku to PlanetScale might seem like a straightforward switch, but the real magic is in how PlanetScale’s sharding architecture fundamentally changes your scaling strategy.

Let’s see it in action. Imagine you have a growing user base and your current Heroku Postgres database is starting to show strain. You’ve hit read replica limits, and writes are becoming a bottleneck.

Here’s a typical Heroku Postgres setup:

heroku addons
# ...
# postgresql-slippery-7890 (HEROKU_POSTGRESQL_COLOR)
# ...
heroku pg:credentials:url HEROKU_POSTGRESQL_COLOR
# postgresql://user:password@host:port/database

On PlanetScale, you’d provision a new database, say my-app-db. Instead of a single monolithic instance, PlanetScale encourages a sharded approach. You might start with a single shard, but the system is built to distribute data across multiple shards automatically as needed.

Consider this PlanetScale schema definition:

CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) SHARD_KEY(id);

CREATE TABLE orders (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    product_name VARCHAR(100) NOT NULL,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
) SHARD_KEY(user_id);

The SHARD_KEY is the crucial lever here. For the users table, sharding by id means that all users with a specific range of IDs will live on the same physical shard. For orders, sharding by user_id ensures that all orders belonging to a particular user are collocated on the same shard. This collocation is key for efficient joins and transactions.

When you deploy this schema to PlanetScale, it doesn’t just create a table; it initiates a schema migration. You can see the progress in the PlanetScale UI or via their CLI.

pscale branch deploy my-app-db main

This command triggers the deployment of your main branch changes to your production my-app-db database. PlanetScale handles the underlying infrastructure, ensuring zero-downtime schema changes.

The problem PlanetScale solves is the "monolithic database bottleneck." Heroku’s approach is often a single, powerful instance that you scale vertically (more RAM, CPU) or horizontally with read replicas. This works for a while, but write scaling and managing large datasets become increasingly complex and expensive. PlanetScale, by its nature, scales horizontally by distributing data. When your users table grows to billions of rows, PlanetScale can automatically split shards, distributing the load across more machines.

Internally, PlanetScale uses Vitess, a database clustering system for MySQL. Vitess handles query routing, connection pooling, and shard management. When you query SELECT * FROM orders WHERE user_id = 12345;, Vitess knows exactly which shard user_id = 12345 resides on and routes the query directly there. If you perform a join like SELECT u.username, o.product_name FROM users u JOIN orders o ON u.id = o.user_id WHERE u.id = 12345;, Vitess can execute this efficiently because users and orders for user_id = 12345 are on the same shard.

The mental model shifts from "my database server" to "my distributed database system." Your application code interacts with PlanetScale through a standard MySQL connection, but the underlying system is intelligently distributing and managing your data. You control scaling not by upgrading a single server, but by choosing appropriate shard keys and letting PlanetScale handle the distribution.

What most people don’t realize is that PlanetScale’s SHARD_KEY choice isn’t just about performance; it’s about data locality for joins and foreign key constraints. If you have a foreign key relationship where the parent and child tables are sharded on different keys, PlanetScale might need to perform cross-shard joins, which can be significantly slower and more resource-intensive. Designing your shard keys to align related data is paramount.

The next challenge you’ll likely face is understanding and optimizing complex analytical queries that might span multiple shards.

Want structured learning?

Take the full Planetscale course →