A preview environment is a temporary deployment of your application created for one pull request, reachable at its own URL, and destroyed when that pull request closes. It is sometimes called a review app, an ephemeral environment, or a PR environment.
The idea exists because shared staging has two properties that fight each other: it is long-lived and it is shared. Long-lived means it drifts from production. Shared means one person's broken deploy blocks everyone else. A per-PR environment is neither, which removes both problems and creates a different one, covered further down.
The lifecycle
Three events, all automatic:
- Created when a pull request is opened.
- Updated when a new commit is pushed to that branch.
- Destroyed when the pull request is merged or closed.
That is the whole model. Everything else is configuration around those three points.
| Shared staging | Preview environment | |
|---|---|---|
| Lifecycle | Long-lived | One pull request |
| State | Drifts, accumulates manual fixes | Rebuilt from the branch every time |
| Isolation | One environment, every feature | One per change |
| Concurrency | A queue, negotiated in Slack | Parallel by construction |
| Cost model | One environment, always on | Depends entirely on the platform: per-environment billing on usage-priced hosts, nothing extra on a fixed-capacity plan |
That last row is where most comparisons are misleading, so it is worth being precise. On a platform that bills per running service, twelve open pull requests means twelve line items. On a fixed-capacity plan the previews run inside capacity you already bought, so the bill does not move. Same feature, opposite cost behaviour.
What it actually replaces
The queue. The single most common use of a shared staging environment is asking, in a channel, whether anyone else is using it. That is a scheduling system made of etiquette. Per-PR environments delete it.
The "works on my branch" gap. Reviewers who cannot easily run your branch tend to review the diff and approve the intent. A URL in the pull request lets a designer check the actual rendering and a product manager click through the actual flow.
Some configuration drift. Nothing lives long enough to drift. This is a real gain, though a partial one: the environment is only as production-like as the config it is built from, so drift moves from the environment into your deployment config, where at least it is in version control.
How it works
The pieces are a Git provider, a builder, and somewhere to run the result.
- A pull request is opened. The Git provider sends a webhook.
- The platform checks out the branch and builds an image, from a Dockerfile or a buildpack.
- It provisions the application and whatever backing services the environment is configured to get, then injects configuration.
- It deploys, generates a URL, and comments on the pull request with the link.
- Each new commit repeats steps 2 to 4.
- Closing or merging the pull request triggers teardown.
Configuring them on Miget
Preview environments are a built-in feature rather than a pipeline you assemble. The settings that matter are on the parent application, which is the app deploying your main branch.
When an environment gets created. Three trigger modes. Auto creates one for every pull request. Label creates one only when a chosen label is applied, which is the setting most teams want after the first week, because most pull requests do not need a URL. Branch pattern matches against the head branch, for example feature/*.
When it gets destroyed. Four independent conditions, not one setting: on merge, on close, on branch deletion, and on inactivity. Cleanup on merge is on by default; the others are off. Inactivity has its own window in days, and there is a separate retention window if you want an environment to survive its pull request for a fixed period.
What gets cloned into it. Addons are selected individually rather than by a single on or off switch, so a preview can get a fresh Postgres without also getting a copy of every queue and cache attached to the parent.
Where it runs. A preview environment can be placed on a different resource than production. This is worth doing: it means a pull request cannot compete for memory with the thing serving your users.
Whether it comments. Posting the deployment status and link back to the pull request is on by default, and is most of the value for reviewers who never open the dashboard.
Auto-deploy on push is on by default, which is what makes the environment track the branch rather than the commit that opened the pull request.
The part nobody solves
Preview environments give you an isolated environment. They do not give you production's data, and no platform's marketing should convince you otherwise. The options are the same three you have anywhere:
Seed data. Deterministic, safe, and nothing like production. Fine for a smoke test, useless for finding the query that only degrades at ten million rows.
Anonymised production dumps. Realistic and expensive to maintain. The day the anonymiser misses a new column is the day personal data lands in a place it should not be. If you go this way, that script needs tests, and its failure mode should be refusing to export rather than exporting something unmasked.
A read replica. Realistic by construction and dangerous by construction. Acceptable only while the environment genuinely cannot write.
Pick one deliberately and write down which. This is the same trade-off that makes a staging environment hard to keep honest, and it does not get easier when the environment is ephemeral.
When you still want staging
Per-PR environments do not replace staging entirely, for one specific reason: some third-party integrations need a URL registered in advance. OAuth callbacks and webhook endpoints are the usual cases, and a URL that changes with every pull request is useless to them. Teams with those integrations generally keep a small staging environment for them and use previews for everyday review.
Frequently asked questions
What is a preview environment?
A temporary, fully deployed copy of your application built from a single pull request's branch, reachable at its own URL, and deleted when that pull request closes. The point is to review a change as a running application rather than as a diff.
What is the difference between a preview environment and staging?
Staging is one shared environment that lives permanently and holds the release candidate. A preview environment exists only for the life of one pull request. Previews remove the queueing and most of the configuration drift; staging keeps the stable URL that some external integrations require.
Do preview environments cost extra?
That depends on the pricing model, not the feature. On usage-priced platforms each environment is billed while it runs, so the cost scales with how many pull requests are open. On a fixed-capacity plan they run inside capacity you have already paid for and add nothing to the bill.
Should every pull request get one?
Usually not. A dependency bump does not need a URL. Most teams start with an environment for every pull request, find it noisy, and switch to creating one only when a label is applied, which keeps the feature for the changes where somebody actually wants to click through the result.
What database does a preview environment use?
Its own, if you configure one. Pointing a preview at the production database defeats the isolation you built it for and gives a half-finished branch write access to real data. Provision a fresh instance per environment and seed it, and accept that seeded data will not surface the problems that only appear at production scale.
How long do preview environments stick around?
Until the pull request closes, by default on merge. If a reviewer needs the URL after the branch is merged, a retention window keeps it for a set number of days, and an inactivity rule can remove environments nobody has touched, which is what stops abandoned pull requests from quietly holding capacity.
What to read next
- What Is a Staging Environment? - Why the shared one drifts, and what previews fix
- Fixed-Capacity PaaS: Predictable Cloud Billing for Devs - Why previews do not appear on the bill here
- Deploy Any Language to Docker Without Writing a Dockerfile - Zero-config builds for preview apps