Build
Stage
The process that turns source code written for people into something a machine can run, sitting ahead of testing and deployment.
Why it exists
For a long time, a developer would type a few commands on their own laptop, get a set of files out of it, and copy those files onto the server. The trouble was that no two laptops were alike. One person was a version ahead on the language runtime, another was still using a library downloaded six months earlier, and a third had a config file they had edited once and forgotten about. The same code produced different outputs, and only the person who uploaded it knew which output was running.
So every incident meeting stalled in the same place. Once someone said "it works on my machine," the conversation had nowhere left to go. Nobody had written down which code or which tools produced the thing that was actually running, so a failure that couldn't be reproduced turned into an exchange of guesses.
The build got its name when this work was taken out of human hands and handed to a machine that does it in the same place, in the same order, every time. Not on somebody's laptop but on one designated server, using only the code that made it into the repository, starting from scratch on every run. Each output then carries a record of the commit it came from, and a failure can be traced back to that commit.
What this stage looks like
The build stage takes source code and produces one deployable package. A pipeline is an automated sequence that chains stages together; the build is its first slot. Everything behind it — tests, deployment — works on the package that comes out of here.
Four steps usually happen inside it.
- Fetch dependencies. Libraries written by other people get pulled in at the versions listed in a manifest. If the versions aren't pinned exactly, yesterday's build and today's build end up using different code.
- Transform. Syntax written for humans is converted into a form the runtime understands — stripping out type annotations, or lowering recent language features into older ones an outdated browser still knows.
- Bundle. Scattered files are combined into deployable units and dead weight is stripped out. On the browser side a bundler handles this step.
- Stamp. The resulting package gets a version and a commit hash baked into it. That stamp is what answers "which code is in production right now?" months later.
No person steps into this stage. It starts on its own when code lands and runs to the end without anyone choosing anything. It takes under a minute on a small service and can run past twenty minutes on a repository with tens of thousands of files, which is why teams cache fetched dependencies and reuse them on the next run.
When it fails, everything stops there. A syntax error, a call to a function that doesn't exist, or a library that can't be downloaded breaks the build, and the tests never start. The cheapest and fastest check a team has sits right here.
What moves you to the next one
Finishing the build is not by itself enough to open the next slot. Three things usually get checked before the test stage begins.
- Did the build command succeed? Machines report success and failure as a single number, and anything other than zero halts the pipeline on the spot. Whether warnings count as failures is a team decision. Rule violations caught by a linter tend to get promoted to failures, because nobody fixes a warning.
- Did a package actually come out, and did it get stored? A package that lives only on the build server disappears the moment that server moves on to its next job. It has to be pushed to an artifact repository so that testing and deployment pull the same object.
- Does the same code produce the same result? If today's output differs from yesterday's, the thing that passed the tests may not be the thing that reaches the server. Pinning library versions and keeping timestamps and random values out of the output covers most of it.
With all three in place, the package gets carried through the environments one at a time. Development, staging, and production are separate execution spaces with different purposes, and switching between them is not a reason to rebuild. Rebuilding puts something other than the tested object into production. The difference between environments comes from environment variables instead — the same package pointed at a sandbox payment server in staging and the real one in production.
How it sounds at work
"The build is broken. Start with the commit that just landed."
The pipeline stopped at its first slot because of code merged moments ago, so everything queued behind it is waiting.
"It built fine, it's the tests that are failing."
Syntax and dependencies were correct but the behavior wasn't, which points the fix at the logic rather than at configuration.
"The build takes eighteen minutes, so I run it and go get coffee."
It sounds like a joke, but it's a complaint about slow feedback, and it's usually followed by a proposal to add caching or split the checks.
At Pagedeck the build runs automatically every time Theo merges code. A green bar at the top of the screen means it passed, red means it failed, and whoever merged gets notified immediately. There's one rule: nobody goes home leaving the bar red. While the build is broken, nobody else's code can get checked either.
Mia watches the same screen for scheduling reasons. In a week where the build breaks often, she doesn't pull a release date forward. More breakage means the checks people run before merging have gotten loose, and pulling the date in from there tends to push rushed fixes through unverified.
What people get wrong
The most common mistake is reading a successful build as proof that the code is correct. The bar is green, so it must be fine — but the only thing confirmed is that a machine could translate this code into a runnable form. Code that sends you to the wrong screen when you press the login button builds perfectly well as long as the syntax holds. Trusting the green bar breeds the habit of skipping tests, and then customers become the first reviewers.
Assuming a package built on your own laptop is fine to upload comes from the same root. Same code, same command, same result — that's the reasoning. But a laptop holds files that never made it into the repository along with personal settings, so nobody can reproduce what came out of it. When something breaks there's no code to trace back to and no previous package to roll back to. The fix is not more discipline about what sits on a laptop; it's making the server the only place a shippable package can come from.
Easily confused with
| Term | What it refers to | How it differs from build |
|---|---|---|
| Artifact | The deployable output a build produces | The build is the process, the artifact is what the process leaves behind. Builds run again and again; one artifact is made once and reused across every environment |
Where to go next
Last updated 2026-09-16