Artifact
Artifact
A single bundled output of a build, kept and named so that the exact thing which passed testing is the thing deployed to every environment.
Why it exists
Deployment used to be manual. A developer turned code into a runnable form on their own laptop and copied the result onto the server. The trouble was that a fresh copy got made every time something went out — one for the test server, then another one days later for the real server. Both started from the same code, so everyone assumed both produced the same thing. They didn't. A third-party library might have released a new version in between, or the tooling installed on the machine had moved on.
Pagedeck got caught by exactly this. Theo spent three days verifying the checkout screen on the test server, confirmed it was clean, and pushed to production on Thursday evening. The payment window refused to open. Not one line of code had changed. The Thursday rebuild had pulled in a newer release of a date-handling library, and one function in that release behaved differently than before. The thing that was tested and the thing that shipped were two different things.
The artifact closes that gap. Instead of treating source code as the unit that travels, it treats the built output itself as an object — give it a name, put it in a store, and move that one object wherever it needs to go. Build once, deploy many comes from here. The guarantee that what was tested is what is running gets anchored to an object rather than to a source tree.
What goes in it
One bundle holds everything the software needs in order to run on its own, on a server that knows nothing about it. Four things go in.
- The software itself, converted into a runnable form. For a web front end that means the bundled files a browser can read. For a server program it means an executable or a container image, a container being a unit that wraps a program together with everything it needs so it behaves identically on any host.
- The assets the interface depends on — images, fonts, stylesheets. None of it is code, and the screen falls apart without it.
- The outside libraries the code calls, pinned to exact versions and packaged alongside. Shipping only a list of names and letting the server fetch whatever is current at deploy time reproduces the checkout failure above, step for step.
- A label saying what this object is. It carries a version number, the time the object was produced, and an identifier pointing back at the code change it came from. When production breaks at 2am, that label is how anyone traces what is actually running back to a specific commit. Version numbers usually follow semantic versioning, which gives each release three numbers separated by dots.
What stays out is just as fixed. Environment variables and anything covered by secret management never go inside. An environment variable is a configuration value plugged in differently wherever the software happens to run; a secret is one of those values that must not leak, like a payment key or a database password. Bake them in and the staging bundle and the production bundle stop being the same object, which is the one thing this whole idea exists to prevent. Those values live outside the bundle and get injected at the moment the program starts.
Who writes it and who reads it
The producer is a machine, never a person. When Theo merges his change into the shared branch, the build stage of the pipeline assembles the bundle automatically and files the one that passed into a store. A pipeline is the automated chain that runs build, test and deploy in order, stopping the moment a stage fails. If even one route stays open for someone to build on a laptop and upload by hand, that route becomes the one that skips the checks. Funneling every bundle through a single producer is the precondition for the rest of this to mean anything.
Four groups read from the store.
- The deploy stage reads it first. Pushing to a test environment and pushing to production both pull the same object out of the store.
- Whoever runs acceptance checks. This is the point at which "the screen Mia approved on the test server is the screen customers see next week" becomes literally true rather than roughly true.
- Whoever handles incidents. A rollback is not reverting the code and rebuilding it — it is pulling yesterday's object off the shelf and putting it back. With the build step skipped, it lands in minutes.
- Whoever reviews security. Because the object records which library went in at which version, a newly disclosed vulnerability can be narrowed to the exact releases affected instead of a guess.
So artifacts don't get thrown away once a deploy finishes. They accumulate, one per version. Each team sets its own retention window, and the working rule is to keep them longer than the furthest point you might ever need to roll back to.
How it sounds at work
"We're shipping the exact artifact we verified on staging, right?"
Checking that nobody rebuilt anything in between.
"Which version is running right now? The artifact label still has the commit on it?"
Tracing the object sitting on a failing server back to a specific code change.
"Rolling back just means redeploying yesterday's artifact. Five minutes."
Saying the thing to roll back to is still sitting in the store, ready to go.
At Pagedeck, no human hand touches the process from the moment Theo merges. The machine assembles the object, files it under a number, and the test server pulls that number and runs it. Mia looks at the screen, says it can go, and the production server pulls the same number. Nobody asks which laptop it came from or what day it was assembled, because both answers are written on the object.
When someone in a meeting says "1.4.2 went out," that number names an object, not a branch of code. The distinction sounds pedantic until the first time a version number is the only thing standing between a broken checkout and a five-minute recovery.
What people get wrong
The most common assumption is that identical code produces an identical output whenever you build it. Code looks like the original and the build looks like a mechanical conversion, so the conclusion comes easily. But that conversion reaches out for outside libraries and tooling as they exist at that moment, and a different moment means different ingredients. Teams that don't believe this keep the habit of rebuilding per environment, and every few months a feature that behaved perfectly on the test server breaks in production alone.
The second one is that artifacts can be deleted once the deploy is done. The software is already on the server, the stored copy looks redundant, and storage costs money. But the moment you need to go back always arrives without warning, and an empty store means starting over from a rebuild. A five-minute recovery stretches into thirty, and the freshly rebuilt object carries no guarantee that it matches what was running yesterday.
Easily confused with
| Term | What it refers to | How it differs from an artifact |
|---|---|---|
| Build | The process of turning source code into a runnable output | One is a process and the other is the object that process emits. A build can be rerun any number of times; an artifact is produced once and carried unchanged from environment to environment |
Where to go next
Last updated 2026-09-16