Skip to main content
Selective Delivery delivers only the targets whose Bazel-built outputs actually changed, driven by the same build graph you already trust. In a monorepo with hundreds of deliverable artifacts, that turns “push everything on every green build” into a handful of uploads per commit.

The problem

Pushing every artifact on every green build is slow and introduces risk: you may push a binary whose inputs did not change, overwriting a known-good artifact with an identical but unverified one. It also wastes CI time and registry storage on uploads that change nothing. You want to push only the artifacts whose build outputs actually changed since the last release.

How it works

Selective Delivery determines what changed using the content hash of each build output, not the git SHA or a timestamp. If Bazel produces the same output digest for a target, that target is not pushed, even if unrelated files changed in the same commit. This is the same cache-key logic Bazel uses internally, applied at delivery time. From trigger to upload, a delivery run:
  • Triggers on green builds of release branches. Running on main is typical, but you have full control over which branches and tags delivery runs on in your CI configuration, and you declare the build and test jobs it depends on there too, so delivery only runs when they pass.
  • Compares output digests against the prior release to find the targets whose outputs actually changed. With Build without the Bytes, the comparison works from hashes alone and never downloads an artifact, so determining what to deliver costs almost nothing, even across hundreds of deliverable targets.
  • Builds resolved targets with version-control stamping enabled, so the pushed artifact carries the correct build metadata.
  • Runs push logic in parallel across the delivery targets, uploading each changed artifact to its configured destination: a container registry, object store, or other target.
  • Produces a delivery manifest: a structured record of every target’s outcome and CI metadata, uploaded as a CI artifact. The manifest is customizable and can be enriched with AXL hooks, for example to attach OCI image digests or feed downstream deployment tooling.

Why digests, not git SHAs

Version stamping is the usual obstacle here: if every artifact embeds the commit SHA, then every artifact differs on every commit and nothing can be skipped. Selective Delivery sidesteps the trap by comparing unstamped outputs to detect change, then rebuilding only the changed targets with stamping for the actual push. You get accurate change detection and correctly-stamped artifacts.

What you get

  • Faster delivery. Only changed targets rebuild and upload, so release pipelines finish in a fraction of the time.
  • Lower cost. No redundant uploads burning CI minutes, registry storage, and network egress.
  • Safer releases. Known-good artifacts are never overwritten by unverified rebuilds of identical content.
  • Simple configuration. Adding a new delivery target is as easy as adding a new Bazel target; teams configure and maintain their own.
  • Auditable. Each delivered artifact traces back to the monorepo state that produced it.
To learn more about Selective Delivery, see the Stamping Bazel builds with selective delivery article.
Selective Delivery is implemented as the aspect delivery AXL task. The task page covers configuration, the delivery script contract, and how to wire it into your CI pipeline.