Remote cache
A remote cache lets heph share build artifacts across machines. CI jobs and developers with the same inputs get cache hits from artifacts another machine already built — without re-executing.
How it works
- A machine builds a target and writes the artifacts to its local cache.
- heph pushes those artifacts to the remote cache on a background task — the build's critical path does not wait on the network.
- A second machine with the same inputs misses locally and checks the remote. A matching entry there is enough to call it a cache hit and skip re-executing — the actual output bytes download afterward, lazily, and only for the outputs something reads.
Uploads are best-effort: a remote failure logs a warning but never fails the build. After three consecutive failures a cache is paused with an exponential backoff, and automatically resumes on its own the next time a request to it succeeds.
Bucket layout
Objects are keyed by target address, so a bucket browses like the source tree — inspecting it in the S3/GCS console shows which target owns which artifact:
| Target | Object key |
|---|---|
//some/pkg:tgt | some/pkg/tgt/<inputhash>/out.tar |
//some/pkg:tgt@v=linux,vp=arm64 | some/pkg/tgt@v=linux,vp=arm64/<inputhash>/out.tar |
//:root_tgt | root_tgt/<inputhash>/out.tar |
<inputhash> is the target's input hash — the same value that drives local
cache hits.
Treat the layout as read-only: don't script against it, since it's not a part of heph's stable API and can change between versions. If it does change, existing objects are simply never read again — the next build repopulates the cache under the new layout, no cleanup needed.
Setting up S3
Add a caches: block to .hephconfig:
caches:
shared:
uri: s3://my-bucket/heph-cache
heph reads credentials from the environment using the standard AWS credential
chain — AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, AWS_PROFILE, or an
instance/workload-identity role.
Setting up GCS
caches:
shared:
uri: gs://my-bucket/heph-cache
Credentials come from GOOGLE_APPLICATION_CREDENTIALS or Application Default
Credentials. In CI, a Workload Identity binding or a service account key file
both work.
Read-only and write-only caches
Set read or write to false to restrict what a cache does. A common
setup: CI writes, developers only read.
caches:
shared:
uri: s3://my-bucket/heph-cache
read: true
write: false # developers read; CI writes
Multiple caches
Configure more than one cache — for example a fast regional store and a slower central one:
caches:
regional:
uri: s3://eu-bucket/heph-cache
central:
uri: s3://us-bucket/heph-cache
heph reads from the fastest cache first and writes to both. Latency is measured once per process and persisted so subsequent runs skip the probe.
Measuring latency
Force a fresh latency measurement and see per-cache round-trip times:
heph tool cache measure-latency
Output lists each cache, fastest first:
Remote cache latency (fastest first):
1.23ms [rw] regional (s3://eu-bucket/heph-cache)
18.45ms [rw] central (s3://us-bucket/heph-cache)
The [rw] flags show the configured read/write permissions. The order
is persisted and reused automatically until the cache definitions change.
Excluding targets from the remote cache
Some targets produce outputs that embed host-local paths — a wrapper script that references an absolute path in a local toolchain store, for example. Sharing those artifacts causes another machine to pull a wrapper that points at a path it doesn't have, which fails at run time.
Set cache = {"remote": False} on those targets. Local caching stays on;
heph will never upload the artifact to or download it from a remote cache:
target(
name = "local-wrapper",
driver = "exec",
run = ["./gen-wrapper.sh"],
out = "wrapper.sh",
cache = {"remote": False},
)
Every machine builds its own copy and caches it locally. Targets that depend on it get a local hit on the same machine; other machines build their own copy on first use.
In CI
A typical CI setup: grant write access to CI runners and read access everywhere. The cache fills on every merged build and keeps subsequent runs fast for the whole team.
heph run //... --no-tui
No extra flags needed — heph reads and writes the remote automatically when
caches: is configured.
See Using heph in CI for the broader CI setup, and
caches in the configuration reference
for the full set of options.