Preview environments are easy to sell: every pull request gets a URL, reviewers see the real thing, and fewer bugs hide between staging and production. The trouble starts when every preview becomes a full copy of production.

The trick is deciding which parts deserve isolation and which parts only need believable behavior.

Isolate writes, share reads

Most preview work needs safe writes, not an entire private universe. Give each branch its own write namespace for drafts, uploads, sessions, and mutations. Let read-heavy reference data come from a shared snapshot.

This keeps previews fast while avoiding the classic problem where one reviewer accidentally edits data another reviewer is using.

Expire aggressively

Every preview should have an owner, a creation time, and a removal policy. Tie cleanup to pull request state and add a maximum age. If a preview matters after the branch is closed, promote the artifact or snapshot intentionally.

Cloud bills grow in the quiet corners. Expiration is a product feature for the engineering team.

Make expensive services fake by default

Email, payments, search indexing, ML inference, and video processing should default to local doubles or sandbox providers. The preview should reveal integration shape, not spend real money proving a button can be clicked.

Document the few cases where a real service is required, and make that opt-in visible in the pull request.

Show cost next to status

Build status says whether a preview exists. Cost status says whether it is behaving. A simple daily estimate beside each active environment changes behavior faster than a monthly surprise report.

The goal is not to make previews cheap at all costs. It is to spend money on feedback, not forgotten infrastructure.