Published: September 16, 2026
A Practical Deployment Pipeline
Shipping software safely comes down to one idea: never let untested code reach real users. The industry-standard way to do this is a staged promotion pipeline — code moves through increasingly production-like environments, gaining confidence at each step.
The Three Core Stages
- Development / Staging This is where active work happens.
- Each feature branch deploys to an ephemeral or shared dev environment.
- Connected to test/mock data, not real user data.
- Fast feedback loop: linting, unit tests, type checks run automatically on every push.
- Purpose: catch obvious bugs early, cheaply.
- Preview A preview environment mirrors production as closely as possible, but is isolated.
- Every pull request gets its own live URL (common pattern:
pr-123.preview.yourapp.com). - Enables reviewers, QA, and stakeholders to click through real, running code — not just read a diff.
- Runs integration tests, E2E tests (Playwright/Cypress), and visual regression checks.
- Often connected to a staging database or seeded snapshot of production-like data.
- Purpose: validate the change in a realistic setting before it touches real users.
- Production The live environment real users interact with.
- Deploys only from a protected branch (usually
main) after preview approval. - Should be a "promotion" of the exact build artifact that passed preview — never a fresh rebuild — so what you tested is what you ship.
- Guarded by required checks: passing tests, code review approval, and often a manual gate for high-risk changes.
Best Practices That Make This Work
Build once, promote everywhere
Build a single immutable artifact (Docker image, static bundle) at PR time. Promote that same artifact through preview → production instead of rebuilding at each stage. Eliminates "works in preview, broke in prod" from environment drift.
Environment parity
Keep infra, env vars, and dependency versions as close as possible across stages. Differences are where bugs hide.
Feature flags over long-lived branches
Merge to main frequently behind a flag. Decouples deploy from release — you can ship dark code to production and turn it on when ready, with instant rollback by toggling the flag off.
- Automated: tests, security scans, bundle-size checks must pass to proceed.
- Human: at least one reviewer approval before production; a release owner signs off on risky changes.
Ephemeral preview environments
Spin up per-PR, tear down on merge/close. Keeps costs down and prevents preview drift/staleness.
Rollback plan by default
Every production deploy should have a one-click or one-command rollback (previous artifact redeploy, or flag kill-switch) — decided before you need it, not during an incident.
Observability at every stage
Ship logs/metrics/error tracking (Sentry, Datadog, etc.) from preview onward so issues surface before production, not after.
Typical Flow Summary
feature branch → push ↓ CI: lint, unit tests, build artifact ↓ Preview env (auto-deployed) → QA / stakeholder review / E2E tests ↓ PR approved & merged to main ↓ Same artifact promoted → Production (gated, monitored, rollback-ready)
This pattern — used by teams at Vercel, Netlify, GitHub, and most modern SaaS companies — trades a bit of pipeline setup effort for a large reduction in production incidents.