Tutorials Modern Delivery Pipeline Chapter 5

Shipping the Web Half: Cloudflare Preview Deploys, Promotion, and Instant Rollback

DeliveryChapter 5 of the Modern Delivery Pipeline26 minJune 7, 2026Intermediate

Ch 4 built the cluster; the last four chapters built everything up to a deploy. Now we cross the line and actually ship — starting with the web half, because it's the half that deploys in seconds, reverts in seconds, and therefore lets you practice the whole "ship safely" discipline cheaply before applying it to apps (which can't be un-shipped from the App Store nearly so fast).

The platform is Cloudflare Workers, the way this site runs (Next.js via OpenNext). By the end you'll know how to give every PR a real preview URL, promote one immutable build through to production, roll a release out to a slice of traffic before everyone, and undo a bad deploy with a single command — the four moves that turn "I pushed and hoped" into "I shipped and watched."

The Web Deploy, End to End

Here's the whole web half on one diagram. Each box is a move this chapter unpacks.

Loading diagram…

Figure 1 — The web release loop. Preview before merge, promote one immutable version, ramp traffic, watch, and revert in seconds if it's bad. The web half is the cheap place to make all of this muscle memory before Ch 6 applies the same discipline to apps.

A Preview URL for Every Pull Request

Recall the Ch 2 review funnel: the human reviews intent and risk. Nothing helps that judgment more than clicking the actual change instead of imagining it from a diff. On Cloudflare, every version of a Worker can get its own URL without touching production:

# Upload a version WITHOUT making it live. Returns a unique preview URL.
wrangler versions upload
# → Version ID: 7c9f… · Preview: https://7c9f-simpleappshipper-next.<sub>.workers.dev

That preview URL runs the PR's code against real bindings, at the edge, isolated from production traffic. Wire it into CI so every PR comment gets its link, and your reviewer (human or agent) tests the real thing. For projects on Workers Builds (the dashboard CI from web Ch 24), non-production branches get preview deployments automatically; for projects on a CI runner, the wrangler versions upload above is the one-liner that produces the link.

Environments: dev → preview → production

The Ch 1 principle was promotion through environments, each a gate with its own secrets. On Workers that's wrangler.toml environments plus environment-scoped secrets:

Loading diagram…

Figure 2 — Three environments, each more trusted than the last. Secrets are scoped per environment so a preview deploy can never read production keys — the Ch 2 least-privilege idea applied to deploys.

Secrets never live in wrangler.toml or git — they're set per environment and stored encrypted by Cloudflare:

wrangler secret put STRIPE_SECRET_KEY                 # default (production) environment
wrangler secret put STRIPE_SECRET_KEY --env preview   # a different, test key for previews

A preview build that's been tampered with literally cannot read the production Stripe key, because it isn't in its environment. That isolation is a security boundary, not just tidiness.

Build Once, Deploy Many — the Worker Version

The Ch 3 artifact principle has a precise Cloudflare form: a version. wrangler versions upload builds and uploads an immutable, content-addressed version of your Worker and does not route traffic to it. Promotion is then just "point production at this already-built version" — no rebuild:

# 1. Build the immutable artifact once (OpenNext → Worker bundle)
npm run cf:build
wrangler versions upload          # → Version ID: 7c9f… (immutable)
 
# 2. Later, promote that SAME version to production — no rebuild
wrangler versions deploy 7c9f…@100%

The version you previewed and approved is byte-for-byte the version that goes live. This is what makes "it worked in preview" a guarantee instead of a hope — there's no second build between preview and prod where something could drift.

Gradual Deployments: Ramp, Don't Leap

Here's the move that separates hobby deploys from production ones. Instead of flipping 100% of traffic to a new version instantly, send it a slice first, watch, then widen. Cloudflare supports splitting traffic across versions:

# Send 10% of traffic to the new version, keep 90% on the old one
wrangler versions deploy 7c9f…@10% 3a1b…@90%
 
# Watch metrics for a few minutes… then, if healthy, go all in
wrangler versions deploy 7c9f…@100%
Loading diagram…

Figure 3 — Progressive delivery on the edge. A bad version only ever touches the slice you exposed it to. If error rate or latency spikes at 10%, 90% of users never saw it — and widening or reverting is one command. This is the Ch 1 "small blast radius" principle made literal.

The discipline: ramp during a window you're watching, not right before you close the laptop. The point of 10% is that you're looking at the metrics while that 10% flows.

Instant Rollback: The Real Safety Net

Progressive delivery limits the blast radius; rollback erases it. Because every version is retained and immutable, reverting is pointing production back at the last good one — no rebuild, no redeploy from source, seconds not minutes:

wrangler rollback              # revert to the immediately previous version
# or target a known-good one explicitly:
wrangler rollback 3a1b…

Observability: Know Before Your Users Do

A ramp you're not watching is just a slow leap. Three cheap signals tell you whether a version is healthy:

SignalHowTells you
Live logswrangler tailReal-time requests + exceptions as they happen — the fastest "is the new version throwing?" check.
Errors + latencyWorkers Observability / dashboard analyticsError rate and p50/p99 latency per version — the metrics you ramp against.
Persistent logs[observability] enabled = true in wrangler.toml (or Logpush)A searchable record after the fact, for the incident you didn't catch live.

The rule that ties it together: a deploy isn't done when traffic hits 100% — it's done when you've watched 100% stay healthy. Observability is what makes the "Operate" act from Ch 1 real instead of aspirational. Ch 7 goes deep on this across the whole pipeline.

What This Project Actually Does

Honest status, same as every chapter. This site deploys today with the simplest version of this loop, and the upgrade path is exactly the moves above.

This very chapter ships through that exact flow: npm run check gates it, cf:build + cf:deploy publish it, and if it rendered wrong in production, wrangler rollback would undo it in seconds.

Mental Model — Three Sentences

  1. Give every PR a real preview URL (wrangler versions upload) so reviewers click the change instead of imagining it — the web's TestFlight.
  2. Build one immutable Worker version and promote thatversions upload then versions deploy — so the thing you previewed is byte-for-byte the thing that ships, with no rebuild in between to drift.
  3. Ramp new versions to a slice of traffic before 100%, watch errors and latency while they flow, and keep wrangler rollback as the one-command undo — because the measure of a pipeline is recovery speed, not a perfect record.

Try It Yourself (15 Minutes)

  1. Make a preview. In a Workers project, run wrangler versions upload and open the preview URL it prints. Note that production is untouched — that URL is your per-PR review link.
  2. Inspect your versions. Run wrangler deployments list (or versions list) and see the immutable history. Every one of those is a rollback target.
  3. Practice a rollback. Deploy a trivial change, then wrangler rollback. Time it. That number — seconds — is your real incident-recovery speed.
  4. Tail it. Run wrangler tail against a deployed Worker and hit it in a browser. Watch the requests stream. That's your fastest "is it healthy?" signal during a ramp.

Where This Lands in the Series

The web half is now a watched, reversible, slice-at-a-time release instead of a push-and-pray — and you practiced it on the platform where mistakes cost seconds. That muscle memory is the point, because the next half is less forgiving.

Ch 6 ships the app half — iOS, Android, Mac, and Windows — where "rollback" means a phased-release halt or an expedited review, not a one-command revert, and where the Ch 4 signing identity finally gets used in anger. Same five-act shape from Ch 1, four very different store-shaped endings.

Ch 4: Your Own Build Cluster — The Mac mini + MacBook Pro FleetCh 6: Shipping the App Half — iOS, Android, Mac & Windows Release Pipelines
Git + GitHubGit & GitHub Pro SeriesGit and GitHub practices for branches, pull requests, rebase, history repair, and team review.Ship iOSShip iOS Apps SeriesShipping workflows for iOS apps: signing, TestFlight, App Store Connect, CI, and release hygiene.Production WebProduction Web Apps SeriesProduction patterns for web apps: caching, rate limiting, webhooks, queues, cron jobs, and idempotency.

Ship your apps faster

When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.

Try Simple App Shipper
5 free articles remainingSubscribe for unlimited access