Dispatch Web
All posts

From a commit to your customers: the deployment pipeline

What happens in the minutes between us changing a file and the world seeing it: commit, build, checks, deploy to the edge, cache. Why a broken build cannot take your live site down, and why every version is kept. Fully referenced.


When you send us a content change, something happens that you never see. A file is edited, saved into a history, turned into a website, checked, copied to servers around the world and switched live. That sequence is the deployment pipeline. This post walks through it using this site as the example. The point to take away: a change that fails on the way never reaches your visitors, and every version that did reach them is kept.

Step 0: the source lives in a repository

Every file that makes up this site sits in a Git repository. Git is the tool software teams use to keep the history of a project. Its documentation explains that “every time you commit, or save the state of your project, Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot”[1]. A commit is that picture: the whole site at one moment.

Two properties of Git matter to a business owner. First, nothing can be altered quietly: “Everything in Git is checksummed before it is stored and is then referred to by that checksum. This means it’s impossible to change the contents of any file or directory without Git knowing about it.”[1] Second, it is hard to lose work: “after you commit a snapshot into Git, it is very difficult to lose, especially if you regularly push your database to another repository”[1]. This site’s repository is pushed to GitHub, so the history exists in more than one place.

The pipeline, step by step

Here is the route a change takes on this site. The quotes are from the vendors’ own documentation.

  1. Change. We edit the file. For a post like this one, that is a text file.
  2. Commit. We save a snapshot with a message saying what changed. GitHub’s guidance is to “give each commit a descriptive message to help you and future contributors understand what changes the commit contains”[2]. Larger changes go on a branch first, which “creates a space to work without affecting the default branch”[2].
  3. Build. Astro, the framework this site is built on, turns the source into finished web pages. Its astro build command “builds your site for deployment. By default, this will generate static files and place them in a dist/ directory”[3]. The output is ordinary HTML, CSS, images and a small amount of JavaScript.
  4. Checks. The build is the first check: if a template is broken or a link points at a page that does not exist, the build stops with an error. We also run Astro’s type checker on the code and measure the finished home page with Lighthouse; the figures are published on the home page with the date they were taken.
  5. Deploy. The finished dist/ folder is uploaded to Cloudflare Pages, which “enables you to upload your prebuilt assets to Pages and deploy them to the Cloudflare global network”[4]. One command builds and uploads. Cloudflare can also do the build itself: “You can connect each Cloudflare Pages project to a GitHub or GitLab repository, and Cloudflare will automatically deploy your code every time you push a change to a branch”[5].
  6. Serve and cache. Cloudflare serves the files from its network and caches them close to your visitors. “Every time you deploy an asset to Pages, the asset remains cached on the Cloudflare CDN until your next deployment.”[6]

There is no server to log in to, no database to update and no plugin to hope is compatible.

Why a failed build never replaces the live site

The live site is not a folder on a server that gets overwritten file by file. It is a deployment: a complete set of files uploaded together and then switched on.

Cloudflare decides whether a build succeeded by one rule: “Pages determines whether a build has succeeded or failed by reading the exit code returned from the user supplied build command. Any non-zero return code will cause a build to be marked as failed.”[7] A failed build produces no deployment, so it cannot be half-published. Your visitors keep seeing the last deployment that did succeed, and Cloudflare’s own list of what you can return to is defined the same way: “Any production deployment that has been successfully built is a valid rollback target.”[8]

On this site the build runs before the upload starts, so a broken build never even leaves our machine. The upload only happens after astro build has finished without error.

Every deployment is kept

Deployments are not thrown away when the next one lands. If a change is wrong in a way the checks could not catch, such as a typo in a phone number, we do not need to rebuild anything: “Rollbacks allow you to instantly revert your project to a previous production deployment”[8], and “when confirmed, your project’s production deployment will change instantly”[8]. Rolling back is itself reversible: “When your project has rolled back to a previous deployment, you may still rollback to deployments that are newer than your current version.”[8]

Each deployment also gets its own address. Cloudflare’s preview deployments “allow you to preview new versions of your project without deploying it to production”[9], at a URL with a random code in front of the project name, such as “373f31e2.user-example.pages.dev - where 373f31e2 is a randomly generated hash”[9]. Custom domains “will not be affected by preview deployments”[9]. That is how we can show you a change before it goes live. The next post in this series is about those preview links and how to give feedback on them.

What can go wrong, and what the visitor sees

Every step has a failure mode. What matters is what your customer experiences at each one.

Step What can go wrong What the visitor sees
Change We edit the wrong thing, or miss something Nothing yet. Nothing has been published.
Commit A change is committed with a bad message, or to the wrong branch Nothing. Git records the snapshot; the live site is untouched[2].
Build A broken template, a missing image, a link to a page that does not exist Nothing. The build stops with a non-zero exit code and is marked failed[7]. The previous deployment stays live.
Checks A page is slower or less accessible than it should be Nothing, if we act on the numbers before deploying. This is why we measure every release.
Deploy The upload is interrupted, or the change is wrong in a way no check catches For an interrupted upload, nothing changes. For a wrong change that went live, the fix is a rollback, which changes production “instantly”[8].
Cache A visitor’s browser, or one of Cloudflare’s data centres, still holds an old copy Possibly the old page, briefly. See the next section.

Notice that four of the six rows begin with “nothing”. That is the design. Failure happens before the switch, not after it.

The last mile: caching

Caching is the one step where a visitor can see something out of date. A cache is a saved copy kept close to the person asking, so the page arrives faster. Cloudflare keeps copies in its data centres, and the visitor’s browser keeps its own.

Cloudflare explains the browser side: “Pages always sends Etag headers for 200 OK responses, which the browser then returns in an If-None-Match header on subsequent requests for that asset.”[6] The browser asks “has this changed?” and only downloads the file again if the answer is yes. On Cloudflare’s side, cached copies “have a time-to-live (TTL) of one week but can also disappear at any time. If you do a new deploy, the assets could exist in that data center up to one week”[6]. If a stale copy ever lingers after a deployment, the documented fix is a purge: “go to your zone and then Caching > Configuration > Purge Everything to ensure the latest deployment gets served”[6].

We also tell browsers how long to keep things, through “a plain text file called _headers without a file extension, in the static asset directory of your project”[10]. In this site’s build, Astro puts every stylesheet, script and font under /_astro/ with a fingerprint in the file name, so a changed file always gets a new name. That lets us mark those files as cacheable for a year and immutable, following the pattern in Cloudflare’s own example, Cache-Control: public, max-age=31556952, immutable[10]. The HTML pages themselves are not marked that way, so a returning visitor gets the new page, and the new page points at new file names. Old and new can never be mixed.

What this means for you

When a quote says “we host it”, ask how a change gets from their desk to your customers. The answers you want: the source is in version control, a build turns it into the site, the build can fail without touching what is live, each version is kept and can be restored, and previews exist before anything goes live. That is what the Live stage of our process means by running the hosting and deployment pipeline.

If you are planning a build, the brief builder takes about three minutes, and the reply comes back with a recommended approach and a fixed price. For what the build step actually produces, read what React is and how we use it without paying for it everywhere.

Reference list

All sources accessed 26 March 2026.

  1. Chacon, S. and Straub, B. (2014, 2nd edn) 'Getting Started: What is Git?', in Pro Git. git-scm.com. https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F
  2. GitHub (n.d.) GitHub flow. GitHub Docs. https://docs.github.com/en/get-started/using-github/github-flow
  3. Astro (n.d.) CLI Commands: astro build. Astro documentation. https://docs.astro.build/en/reference/cli-reference/#astro-build
  4. Cloudflare (n.d.) Direct Upload. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/get-started/direct-upload/
  5. Cloudflare (n.d.) Git integration. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/git-integration/
  6. Cloudflare (n.d.) Serving Pages. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/serving-pages/
  7. Cloudflare (n.d.) Build configuration. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/build-configuration/
  8. Cloudflare (n.d.) Rollbacks. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/rollbacks/
  9. Cloudflare (n.d.) Preview deployments. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/preview-deployments/
  10. Cloudflare (n.d.) Headers. Cloudflare Pages documentation. https://developers.cloudflare.com/pages/configuration/headers/

Unfamiliar word? Every term in this post is defined in one sentence in the glossary.

Written by Dispatch Web. Corrections and questions: send them through the brief builder and mark them as a note; they reach the same board.