Shadow branching lets you test schema changes on a live database without impacting production traffic.

Let’s see it in action. Imagine you have a PlanetScale database, and you want to add a new email column to your users table. This is a common scenario, and usually, you’d have to take your application offline, apply the schema change, and hope for the best. With shadow branching, that risk is eliminated.

Here’s the workflow:

  1. Create a New Branch: You start by creating a new branch from your production branch. This new branch is essentially a copy of your production schema, but it’s isolated.

    pscale branch create my-database main --name feature/add-email-column
    

    At this point, main is still serving all your production traffic. feature/add-email-column is a separate, inactive schema.

  2. Apply Schema Changes to the Branch: Now, you make your desired schema change on this new branch.

    ALTER TABLE users ADD COLUMN email VARCHAR(255);
    

    You can run this ALTER TABLE statement directly in the PlanetScale schema editor or via the pscale CLI.

  3. Enable Shadowing: This is where the magic happens. You tell PlanetScale to "shadow" your production branch (main) onto your feature branch (feature/add-email-column). This means that all read traffic hitting main will also be mirrored to feature/add-email-column.

    pscale branch shadow main --name feature/add-email-column
    

    Crucially, write traffic still only goes to main. The feature/add-email-column branch only receives read traffic. This allows the new schema to be tested against real-world queries without any risk of data corruption or downtime.

  4. Test Your Application: You then point a subset of your application traffic, or a dedicated testing environment, to the feature/add-email-column branch. You can run automated tests, perform manual checks, or even enable this branch for a small percentage of your actual users. Because the branch is receiving read traffic, your application will "see" the new email column and interact with it as if it were in production. If the schema change causes any unexpected behavior (e.g., a query fails, performance degrades), it only affects the shadowed traffic, not your production users.

  5. Deploy or Discard:

    • If everything looks good: You can then promote the feature/add-email-column branch to main. This is a seamless, zero-downtime deployment.
      pscale branch deploy feature/add-email-column --to main
      
      PlanetScale will apply the schema change to the main branch, and all traffic will now use the updated schema.
    • If something is wrong: You can simply discard the feature/add-email-column branch without any impact on your production database.
      pscale branch delete feature/add-email-column
      

The core problem shadow branching solves is the inherent risk of schema migrations. Traditionally, migrations are a "big bang" event: you apply the change, and then you pray. This often leads to lengthy maintenance windows, rollback procedures, and the anxiety of potentially breaking your production application. Shadowing de-risks this entirely by allowing you to validate schema changes against live, production read traffic in a completely isolated environment.

Internally, PlanetScale achieves this by intercepting read requests destined for the production branch and replicating them to the shadowed branch. The shadowed branch executes these queries against its own copy of the schema. Any errors or performance regressions are detected on the shadowed branch and reported, while the production branch remains unaffected. This replication is done at the database level, so it’s transparent to your application code.

The key levers you control are the branch creation, the schema modifications, and the enablement/disablement of shadowing. You can also control which traffic hits the shadowed branch by routing specific application instances or traffic segments to it. This allows for graduated rollouts and testing with confidence.

What many users don’t realize is that shadow branches are not just for schema changes. You can use them to test application code against a replicated production database. Deploy a new version of your application pointed at the shadowed branch. It will read from the shadowed branch’s schema but write to the production branch. This allows you to test application logic and compatibility with the current production schema before merging code that relies on the new schema.

Once you’ve successfully deployed a schema change via shadowing, you’ll naturally want to consider how your application code needs to adapt to the new schema, which leads into feature flagging for application code deployments.

Want structured learning?

Take the full Planetscale course →