ArtifactsGENERALPLATFORM-SPECIFIC

What an Artifact Is

The immutable, stored, addressable output of a build — the unit that gets tested, promoted, deployed and rolled back.

The question, the obvious approach, and why it breaks

Every lesson starts where the work starts: an operational problem, a first attempt that is entirely reasonable, and the way production disagrees with it.

The production question

What exactly is the thing that gets deployed, and why does it have to exist before the deploy starts?

The problem

A build produces something. If that something has no name, no storage and no guarantee of immutability, then "what is running in production" is a question about a filesystem on a machine rather than a fact anyone can look up.

What teams do first

The deployable unit is the repository. Deploying means checking out a commit on the target, installing dependencies and starting the process. Git already versions everything, so the commit SHA is all the identity we need.

How it breaks

The build now happens on every target, at deploy time, in an environment nobody reviewed. Two machines deploying the same commit an hour apart can resolve different dependency versions and end up running different code (Dependency Pinning).

How it breaks in production
  • The build now happens on every target, at deploy time, in an environment nobody reviewed. Two machines deploying the same commit an hour apart can resolve different dependency versions and end up running different code (Dependency Pinning).
  • Nothing was tested. The thing CI checked was a build made on the CI machine; the thing serving traffic is a different build made on a server. They share a commit and not much else.
  • A deploy can now fail for build reasons — a registry timeout, a compiler out of disk — which turns a two-minute rollout into a build debugging session while traffic is degraded.
  • Rollback means rebuilding an old commit with today's dependency world, which is a new artifact nobody has ever run. The one moment you most want a known-good binary is the moment you are compiling a novel one.
  • A commit SHA identifies inputs, not outputs. Two builds of one commit are two different sets of bytes, and only one of them is running.
CodeBuildTestArtifactReleaseDeployRunObserveOperateIncidentRecoverLearnImprove

What is actually happening

Underneath the tooling, which is the part that survives a change of tool.

  • An artifact is the output of a build, captured as a single addressable object: a container image, a jar, a wheel, a static binary, a tarball, a machine image, a bundled front-end. The form varies; the properties do not.
  • Four properties make it an artifact rather than a pile of files: it is immutable (the bytes never change after the build), addressable (there is a name that identifies exactly those bytes), stored somewhere independent of the machine that made it, and described by metadata that says where it came from.
  • The artifact is the boundary between "we made something" and "we are operating something". Everything before it is a build concern; everything after it is a delivery concern. Test results, scan results, approvals and release records all attach to the artifact, which is only possible because it has an identity.
  • What is deliberately not in the artifact is as important as what is: environment-specific configuration, secrets, and data. Those arrive at run time, which is what lets one artifact serve every environment (Build-Time and Runtime Configuration).

Forms of artifact, and what is deliberately outside each one

PLATFORM-SPECIFICContainer and serverless platforms enforce the boundary for you — the image is read-only and config arrives as environment. Machine images and system packages do not: nothing stops a post-install script from writing an environment-specific file, which is why VM fleets drift more than container fleets (Environment Drift).

The word covers several shapes. What makes them the same kind of object is the boundary: everything the build decided is inside, and everything the environment decides is outside.

The right-hand column is the one people get wrong. Anything in it that leaks inside the artifact turns one deployable into several, and quietly ends the ability to promote.

FormWhat it containsWhat must stay outside
Container imageFilesystem layers, entrypoint, default env, userEndpoints, credentials, feature flags, tenant data
Jar / wheel / gemCompiled or packaged code and its declared depsDatasource URLs, keys, per-environment tuning
Static binaryThe linked program and embedded assetsEverything the process reads at startup
Front-end bundleHashed JS/CSS assets and an index documentAPI base URLs if they differ per environment
Machine imageOS, runtime, agents, the applicationInstance identity, secrets, mounted data volumes
Serverless packageHandler code and bundled dependenciesEnvironment variables, IAM role, event source config

From source to a stored object

The artifact step is one hop, and it is the hop where identity is created. Before it, everything is reproducible in principle; after it, everything is a lookup.

Where the artifact appears, and what each step owes
  1. 1
    Resolve inputs

    Pin the source commit and the exact dependency set the build will use.

    fails by A floating dependency range resolves differently than it did an hour ago.

    evidence A lockfile or resolved manifest recorded with the build (Dependency Pinning).

  2. 2
    Build

    Turn those inputs into output bytes in a controlled environment.

    fails by The build reads something from the machine it is running on — a local toolchain, a cached credential, the clock.

    evidence The same inputs produce the same output identity (Reproducible Builds).

  3. 3
    Package

    Collect the output into one object with an entrypoint and a declared runtime contract.

    fails by Environment-specific files swept into the package by a wildcard copy.

    evidence The package starts with no environment present and fails loudly on missing config, rather than starting wrong.

  4. 4
    Address

    Compute an identity from the content itself.

    fails by Identity assigned by a human-typed label that can later mean something else (Tags Versus Digests).

    evidence The identity is a hash of the bytes and nothing else.

  5. 5
    Store

    Push it to a registry or artifact store outside the build machine.

    fails by Push fails and the pipeline reports success on the build step that preceded it.

    evidence A read-back from the store returns the same identity that was pushed (Artifact Registries).

  6. 6
    Describe

    Attach provenance: commit, build id, inputs, builder.

    fails by Metadata recorded somewhere the artifact does not travel with.

    evidence Given only the identity, you can reach the commit (Build Provenance).

Everything downstream — tests, scans, approvals, releases, rollbacks — attaches to the identity created in step four. A pipeline that skips it can still deploy; it just cannot answer questions.

Deploying source versus deploying an artifact

Deploying from source is not a beginner's mistake — it is what most deployment tooling did for a long time, and it works until the first time two machines disagree.

The difference is not effort. It is when the build happens, and therefore whether the thing you tested is the thing that runs.

Same commit, two delivery models
Build at deploy time
git pull on host
  -> install dependencies (resolved now)
    -> compile on host
      -> restart process
         (repeat independently on every host)
Build once, store, deploy the object
CI build (inputs pinned)
  -> artifact@sha256:9f3e...
    -> stored in registry
      -> tested as that identity
        -> every host pulls that identity

In the first model each host performs its own build, so "the same version" is a claim about source rather than about bytes, and no test result refers to anything running. In the second, one set of bytes exists, was tested, and is what every host runs — which is what makes rollback a selection instead of a rebuild.

How to do it properly

Most important first.

  • Produce exactly one artifact per build, and store it before anything deploys it. If it is not in the store, it does not exist.
  • Give it an identity derived from its content, not from a label a human typed (Tags Versus Digests).
  • Attach the provenance at build time — source commit, build id, the resolved dependency set, the builder identity — because reconstructing it afterwards is guesswork (Build Provenance).
  • Keep configuration and secrets out. An artifact that only runs in one environment is not an artifact, it is an environment (Artifact Plus Configuration).
  • Never modify a stored artifact in place. If it is wrong, build another one; the wrong one is evidence.

How much can this affect

Every production change has a blast radius. Stated as a scale so it is comparable between changes rather than adjectival — and paired with what actually contains it, because a wide scope with a real containment mechanism is a different situation from a wide scope with none.

Blast radius if this is wrongEveryone
One testEveryone
What contains it

Nothing. If the deployed thing has no identity, every other containment mechanism in this domain — canary, promotion, rollback, audit — loses the reference it is supposed to point at.

What can go wrong

Failure modes, including of the mitigation
  • An artifact produced but never stored, so the only copy is on the CI runner that is about to be recycled.
  • Configuration baked in, which silently converts one artifact into several and makes promotion a rebuild (Build Once, Deploy Many).
  • Secrets baked in — they survive in the artifact and in every copy of it, including the ones you deleted the tag for (Secrets in CI).
  • Metadata attached out of band, in a spreadsheet or a wiki page, which drifts from the artifact within weeks.
  • An artifact store treated as a cache rather than as production infrastructure, so it is unavailable exactly when you need to scale up.
Misreads this invites
  • "The commit is the artifact." The commit is the input. Two builds of one commit are two artifacts, and telling them apart is the entire point.
  • "We use containers, so we have artifacts." Only if the image is built once and stored. An image rebuilt on each environment's pipeline is source distribution wearing an image's clothes.
  • "Artifacts are a container thing." A jar, a wheel, a signed binary and a machine image are all artifacts. Containers made the practice common; they did not invent it.

Operating it

Evidence is the signal, not the intention. Rollback is sometimes 'you cannot, and that is the point'.

How you know it worked
  • For the version currently serving production you can name the artifact, the build that produced it, and the commit that build consumed — from a lookup, not from a person.
  • Redeploying the same artifact identifier twice produces byte-identical running processes.
  • The artifact that passed the tests is the artifact in the registry, verified by identity rather than by trust.
How you get back
  • Rolling back means selecting a different, already-built artifact. That is fast and boring precisely because no build is involved.
  • If your rollback requires a build, you do not have artifacts — you have a build system with a deployment step attached, and your recovery time includes a compile.
What to automate, and what stays human
  • Automate artifact creation, storage and metadata attachment as one indivisible step in CI. A build that succeeds but does not publish is a build that will be repeated by hand later.
  • Automate the identity check at deploy time: refuse to deploy an artifact that is not in the store with the metadata you require.
  • Keep the decision of which artifact goes where human, or at least gated on evidence — that is release, not build (Deployment Is Not Release).
What this costs
  • Storing every build costs money and grows without bound unless you decide what to delete (Artifact Retention).
  • Keeping configuration out of the artifact means configuration becomes its own deployable, with its own failure modes and its own blast radius (A Config Change Is a Production Change).
  • Immutability means fixing anything — even a one-character typo in a config default — requires a full build cycle. That is the cost of knowing what is running.

Where this applies

This domain is unusually tool- and organisation-dependent. These labels say what each claim is specific to, and what a different platform, provider or organisation does instead.

  • GENERALThe four properties — immutable, addressable, stored, described — hold for any deployable form. What changes is the format and the store, not the requirement.
  • PLATFORM-SPECIFICThe artifact's shape is decided by the runtime: a container platform wants an OCI image, a serverless platform wants a zip or an image the provider re-packages, a VM fleet wants a machine image or a system package. Immutability is guaranteed by the store in the first two cases and by your own discipline in the third.

Where the depth lives

This domain teaches delivery and operation, and hands the mechanism off to the domain that owns it.

Domains that do not exist yet
  • Testing & Reliability Engineering — a test result is only meaningful if it names the artifact it was run against.