Preview Deployment

Method

A deployment style that automatically publishes each code change to its own temporary URL, so the change can be checked as a real screen before it's merged.

Why it exists

Reviewing code before merging has existed for a long time, but what that process looks at is code. Checking how a screen actually renders meant pulling the change onto your own machine and running it. For anyone who isn't an engineer, that route didn't exist at all. Even for engineers, installing a dev environment and checking out the branch made a single look expensive.

At Pagedeck the gap was being filled with screenshots. When Noa wanted to see a screen, Theo ran it locally and posted captures. Showing an empty list, a list with one document and a list with twenty took three images, and a copy change on any one of them meant three more.

There was also only one shared environment for checking. Three people pushed their work to that single place and overwrote each other's screens. A preview deployment makes one of those environments per change. When the number of things to check grows, the number of URLs grows with it, so nobody waits in line. Queueing for a single environment also made people skip the check altogether when they were in a hurry.

How to run it

Push a change and a temporary environment gets built automatically, with its URL attached to the review request. Six steps.

  1. Put the work on a branch off the trunk and open a pull request, the request to merge it. That request is the trigger that builds the environment.
  2. An automated pipeline builds that change alone and publishes it to an isolated environment. Nobody else's work is mixed in. Each request gets a distinct URL, so which change a screen belongs to is identifiable from the address.
  3. Post the URL as a comment on the request. A link that arrives in a notification, rather than one someone has to go find, is what makes this work in practice.
  4. Decide what data that environment sees. Don't wire it to production data; load prepared example data instead. This step is half the process, and loading too little makes the check worth less. Prepare an empty list and a list of twenty in advance and checking both states takes one link. Anonymized copies of production data are the usual middle ground, and they come with their own review.
  5. Two kinds of checking then run in parallel. Code review looks at the code; whoever opens the preview URL looks at the screen. This is where a designer or a product manager checks without going through an engineer.
  6. Destroy the environment automatically when the request is merged or closed. Skip the teardown rule and a few weeks later hundreds of unused environments are running, with the bill to match. Tie teardown to the request's state rather than to a timer, or a long-lived request loses its preview mid-review.

When it fits and when it doesn't

It fits products with screens and teams that change them often. It's worth the most when the person checking isn't an engineer, and when the person who pushed the change and the person checking it sit on different teams. Attach a URL even to a one-word copy fix and whoever asked for the fix decides for themselves. What drops is the number of round trips between asking for a change and accepting it.

Three places it doesn't fit.

  1. Flows with real effects on outside systems. Wire up payments or outbound email as-is and checking the screen charges someone's card. This only opens up once a sandbox exists.
  2. Changes to data structure. When a migration that moves storage into a new shape is involved, what an isolated environment shows won't reproduce in production. It's also the kind of change that's hard to undo, so the checking process gets designed separately.
  3. Screens only visible after login. Without accounts and permissions prepared per environment, the link stops at the first screen. A seeded test account per environment is the usual fix.

The limits are clear too. Cost scales with the number of environments, and thin data hides real problems. A list that's fast at 10 records and slow at 10,000 only gets caught to the extent the example data was prepared. Above all, looking fine in a preview doesn't mean running fine in production. Making the actual switchover safe is the job of production-side strategies like blue-green deployment. Budget for these environments the way you budget for build minutes.

How it sounds at work

"The URL is on the request. You can click through all three states."

Handing off checking as a link rather than as screenshots.

"This change alters storage, so a preview can't verify it. Let's look at it separately."

Some changes aren't covered by this method.

"We have 140 environments left from last month. Let's auto-destroy the ones on closed requests."

There's a rule for creating them and none for removing them.

After Theo added the step to the pipeline, passing screenshots around stopped. Noa clicked the link in the notification and checked directly, catching three copy and spacing problems in the first week before they merged. Fixing the same things after merging would have meant a new request and another review, and the cost difference showed itself right there.

A gap surfaced a month in. The example data held only 10 documents, so nobody saw the list getting slow, and that screen came back as a support question after it reached production. Nobody had asked for a list that long, which is why the gap stayed invisible. Theo raised the example data to 10,000 records. What settled then was that the value of a checking environment is set by the data inside it rather than by the environment.

What people get wrong

The most common reading is that it replaces the staging environment, since both are places to look before production. But this one looks at a single change and staging looks at the merged whole. Remove the last check in a place with production-like data volume and integrations, and there's nowhere left to catch the case where every change works alone and breaks together. The two aren't alternatives; they're a sequence, and staging answers a question a preview structurally can't.

Reading a clean preview as permission to deploy is the other one, because having seen the real screen feels like checking is finished. Several things never surface in an isolated environment: integrations with outside systems, speed that depends on data volume, conflicts that appear when many people work at once. A preview tells you the change renders; it doesn't tell you the system holds. A preview is a pre-merge check, and the deploy decision is a later, different process. Saying what was checked alongside the word "checked" keeps the two apart.

Where to go next

Last updated 2026-09-16