Preview environments let a team test a pull request on a shareable URL before merging it, but an unchecked setup can create unnecessary cloud spend, leak secrets, or alter data that should remain isolated. This guide explains how to choose a preview pattern, connect it to CI/CD, protect databases, control access, and automatically clean up temporary infrastructure.
Overview
A preview environment is a temporary or persistent deployment associated with a branch, pull request, commit, or proposed release. It normally includes the web application and selected supporting services, such as an API, queue, storage bucket, or database. The result is a URL that reviewers, testers, and product stakeholders can use without waiting for a merge into staging.
The right design depends on what needs to be tested. A front-end change may only require a deployment connected to a shared API. A schema migration, authentication change, or multi-service feature may need an isolated application, database, and background workers. Treat preview environments as a controlled part of your staging and release process, not as unrestricted copies of production.
| Pattern | How it works | Best fit | Main trade-off |
|---|---|---|---|
| Per-branch environment | Each branch receives a relatively persistent application URL and configuration. | Long-running features, client review, or parallel team work. | Idle environments and duplicated services can increase cost and maintenance. |
| Shared staging | Pull requests deploy to one common environment, often replacing the previous build. | Small teams, simple applications, or integration testing with shared dependencies. | Concurrent changes can overwrite one another and make failures harder to attribute. |
| Ephemeral environment | CI creates an isolated environment for a pull request and destroys it after closure or expiration. | Automated review, isolated testing, and teams with many concurrent changes. | Provisioning, seed data, migrations, and teardown require deliberate automation. |
For many teams, an ephemeral environment is the most useful default for pull-request review, while shared staging remains valuable for end-to-end tests that depend on stable integrations. A hybrid approach is often easier to operate than trying to make one environment serve every purpose.
Checklist by scenario
For a basic pull-request preview
- Define the trigger. Decide whether previews are created for every pull request, only for selected branches, or only when a label or command is applied. Document who can request one.
- Build from the exact commit. The deployment should identify the repository, branch, pull request, and commit SHA. This makes it possible to connect a URL to the code under review.
- Create a predictable URL. Use a provider-generated URL or a controlled subdomain pattern. Include the pull-request identifier where practical, but do not place secrets or sensitive business data in the URL.
- Publish the URL back to the pull request. A CI comment or status check should show the deployment state, URL, commit, and any required test result.
- Apply an expiration rule. Set a maximum lifetime and remove the environment when the pull request is closed, merged, or abandoned. Add a scheduled cleanup job as a second line of defense.
For a preview that needs an API or database
- Choose the isolation boundary. Decide whether the preview uses a shared API, a separate API deployment, a database branch, a disposable database, or a sanitized snapshot. Record the choice in the repository documentation.
- Use safe seed data. Create deterministic fixtures that cover the flows reviewers need. Never copy production records into a preview unless they have been appropriately sanitized and the transfer is explicitly approved.
- Make initialization repeatable. The environment should be able to create its schema, apply migrations, load seed data, and start from a clean state without manual database edits.
- Separate credentials. Preview services need their own database users, API keys, OAuth applications, storage buckets, and webhook endpoints where possible. Give each credential only the permissions required by the preview.
- Prevent outbound side effects. Route email, payments, text messages, and third-party writes to test endpoints or safe sinks. If a real integration must be exercised, use narrowly scoped test accounts and explicit safeguards.
Database branching can be convenient when the chosen database service supports it, but the operational details vary. Confirm how branches are created, how schema changes are promoted, how storage is billed, and what happens when a branch is deleted. If you are comparing backend options, the database and authentication trade-offs in this BaaS comparison are useful context.
For an application with authentication
- Protect the preview with access control rather than relying on an unguessable URL.
- Choose whether reviewers sign in through a separate identity-provider application, test accounts, or a controlled preview-only login.
- Keep callback URLs, cookie domains, token audiences, and redirect destinations specific to the preview domain.
- Disable account recovery, administrative actions, and elevated roles unless they are essential to the test.
- Ensure preview logs and screenshots cannot expose tokens, personal data, or credentials.
For a multi-service or resource-intensive application
- List every resource created by the deployment: application services, databases, queues, buckets, scheduled jobs, domains, certificates, and monitoring objects.
- Attach a common environment identifier, such as the repository and pull-request number, to names and resource metadata.
- Set limits for CPU, memory, storage, request volume, and worker count so an accidental loop cannot create an open-ended bill.
- Decide which services can be shared safely and which must be isolated. Shared observability or read-only configuration may be acceptable; shared write-capable databases require more caution.
- Test teardown independently. A deployment is not complete until the resources it creates can be removed reliably.
What to double-check
CI/CD behavior
Review the pipeline as a state machine: create, build, deploy, test, report, expire, and destroy. Decide what happens after a failed build, a cancelled job, a renamed branch, a force-push, or a reopened pull request. Avoid allowing every commit to create a new permanent environment unless that behavior is intentional.
Use deployment locks or concurrency controls where two jobs could modify the same preview. Keep the pull-request status accurate when a newer commit supersedes an older one. For broader deployment practices, see this platform-agnostic guide to deploying a web app to the cloud.
Secrets and configuration
Separate build-time values from runtime secrets. Front-end variables may be visible to anyone who can load the page, so never place private keys in client-side configuration. Confirm that preview logs, build artifacts, CI output, and error pages do not print secret values. Review permissions for the CI identity that creates and deletes infrastructure.
Data and integrations
Write down whether preview data is disposable, persistent for the life of a branch, or shared. Define who may access it and how it is deleted. For webhooks, use preview-specific endpoints or test destinations, sign requests where supported, and make handlers idempotent. The webhook reliability checklist covers retries, signatures, and failure handling that also matter in temporary environments.
Cost and observability
Measure the resources created per preview rather than looking only at the total cloud bill. Track active environments, age, owner, last deployment, and estimated resource usage. Apply quotas and idle shutdown where available. Retain enough logs and deployment history to diagnose a failed review, but set retention appropriate to a temporary environment. This complements a wider cloud app cost-optimization review.
Common mistakes
- Copying production data by default. Real data creates privacy, security, and retention concerns. Prefer generated or sanitized fixtures.
- Using production credentials. A preview should not be able to send real email, charge a card, modify production records, or publish to a live queue.
- Deleting only the application. Databases, storage, IP addresses, queues, and scheduled jobs can remain after the visible deployment is gone.
- Relying on manual cleanup. People forget. Use pull-request events, expiration timestamps, and periodic reconciliation against the deployment inventory.
- Making previews too different from production. Temporary environments can be smaller, but differences in runtime, build commands, routing, or database behavior can hide release defects.
- Ignoring access control. A preview URL may expose unreleased features or test data. Require authentication when the content or functionality is not public.
- Failing to test migrations. A preview that starts with a fresh database may not reveal whether a migration works against an existing schema. Include upgrade-path testing where migrations are a release risk.
Keep a short policy in the repository. A practical starting point is: “Every preview is linked to a commit and owner, uses non-production data and credentials, blocks or redirects external side effects, expires automatically, and is removed when its pull request closes. Exceptions require an owner, an end date, and a documented reason.”
When to revisit
Review the preview-environment policy before seasonal planning cycles, major framework or hosting changes, and any migration to a new CI or app deployment platform. Revisit it when the application adds a database, background worker, authentication provider, payment flow, webhook, or other integration with real-world side effects.
At least twice a year, audit the environment inventory and answer these questions:
- Can every active preview be mapped to an open branch or pull request?
- Are expired environments and their dependent resources actually removed?
- Have credentials, access rules, redirect URLs, and third-party test accounts been reviewed?
- Does seed data still represent the workflows reviewers need?
- Do deployment, database-branching, and CI capabilities still match the current provider configuration?
- Are preview costs and resource limits visible to the team?
After each audit, update the repository checklist, CI configuration, and ownership list together. A preview environment is useful when it shortens feedback without introducing a second production system to maintain. Start with the smallest isolation boundary that protects data and integrations, automate its lifetime from creation through teardown, and expand the setup only when a testing requirement justifies it.