Sultan Kautsar Get a quote

A Practical Deployment Pipeline

Shipping software safely comes down to one rule: untested code should never reach real users. The usual way to enforce it is a staged pipeline, where each change moves through environments that look more and more like production, and has to pass checks at every step.

3 min read

The Three Core Stages

1. Development and staging
This is where active work happens.

  • Each feature branch deploys to a shared or short-lived development environment.
  • It runs on test or mock data, never real user data.
  • Linting, unit tests, and type checks run automatically on every push, so feedback is fast.
  • The goal is to catch obvious bugs early, while they are cheap to fix.

2. Preview
A preview environment mirrors production as closely as possible while staying isolated from it.

  • Every pull request gets its own live URL, commonly something like pr-123.preview.yourapp.com.
  • Reviewers, QA, and stakeholders can click through the running change instead of only reading a diff.
  • Integration tests, end-to-end tests (Playwright or Cypress), and visual regression checks run here.
  • It is often connected to a staging database or a seeded snapshot of production-like data.
  • The goal is to validate the change somewhere realistic before real users see it.

3. Production
The live environment that real users interact with.

  • It deploys only from a protected branch, usually main, after the preview is approved.
  • It receives the exact build artifact that passed preview, promoted without a fresh rebuild, so what you tested is what you ship.
  • Required checks guard it: passing tests, an approved code review, and often a manual sign-off for high-risk changes.

Practices That Make It Work

Build once, promote everywhere
Build one immutable artifact, such as a Docker image or a static bundle, when the pull request is opened. Promote that same artifact from preview to production instead of rebuilding at each stage. A rebuild can pick up a different dependency or setting, and that drift is where “it worked in preview” bugs come from.

Environment parity
Keep infrastructure, environment variables, and dependency versions as close as possible across stages. Bugs hide in the differences.

Feature flags over long-lived branches
Merge to main often and keep unfinished work behind a flag. Deploying and releasing become separate steps: the code can sit in production switched off, go live when it is ready, and be switched off again in seconds if something goes wrong.

Automated and human gates

  • Tests, security scans, and bundle-size checks must pass before a change moves on.
  • At least one reviewer approves before production, and a release owner signs off on risky changes.

Short-lived preview environments
Create one per pull request and tear it down when the pull request is merged or closed. That keeps costs down and stops old previews from drifting out of date.

A rollback plan by default
Every production deploy needs a one-click or one-command way back, either redeploying the previous artifact or switching off a flag. Decide it before you need it, never in the middle of an incident. Headless CMS for a Brand Site does this with versioned releases, and A Circuit Breaker for Amazon SES applies the same idea to email sending.

Observability at every stage
Send logs, metrics, and error tracking (Sentry, Datadog, or similar) from preview onward, so problems show up before production.

The Flow in Short

  1. Push to a feature branch
  2. CI runs lint and unit tests, then builds the artifact
  3. Preview deploys automatically for QA, stakeholder review and E2E tests
  4. The pull request is approved and merged to main
  5. The same artifact is promoted to production, gated, monitored and ready to roll back

Setting up a pipeline like this takes some effort up front, and in return far fewer problems reach production.

Related Notes

  1. Headless CMS for a Brand Site

    A practical headless CMS setup for a company brand site using WordPress and Next.js on RunCloud, with Docker, Supervisor, on-demand revalidation, and scripted release, deploy, and rollback.

  2. A Circuit Breaker for Amazon SES

    SES Guard, a small CloudFormation stack that watches Amazon SES for sending spikes and high bounce or complaint rates, stops sending automatically, keeps the logs, and alerts Telegram, PagerDuty, and email with who was sending.

  3. Coding with GPT Astra

    My GPT-6 Astra workflow: high reasoning for planning, low reasoning for implementation, and a practical process for better specifications, code review, testing, and delivery, with a comparison to Sol.

Next step

Have a project in mind? Let's talk.

Tell me what you have and what you need. I'll usually reply within one working day with how I'd approach it.