Configure Go Remote Build Cache
Last updated: August 14, 2026
What is Go Build Cache
The Go toolchain has a built-in Build Cache that reuses outputs from previous builds when the inputs to a build action have not changed.
By default, Go stores this cache locally in the directory configured by GOCACHE. Go can also delegate build-cache storage to an external program through GOCACHEPROG.
There are multiple Open Source implementations of GOCACHEPROG.
platacard/cacheprogis a feature-richGOCACHEPROGimplementation that adds Remote Cache Storage to the Go Build Cache, with support for artifact compression.BuildFetch Cache natively implements the
platacard/cacheprogHTTP Remote Cache Storage protocol in Cloud & On-Prem, allowing Go builds to use BuildFetch as shared Remote Cache.
A Go build is made up of many individual actions: compiling packages, linking binaries, etc.
For each action, Go toolchain computes an ActionID from the complete description of that computation. This includes information such as the command being executed, relevant environment, input files, toolchain executables, build options, and other inputs that can affect the result.
The result of the action is identified separately by an OutputID.
- On a Cache Miss, Go executes the action and sends its resulting output to
GOCACHEPROGfor storage. - On a Cache Hit,
GOCACHEPROGrestores the previously generated output and Go skips that expensive action.
Because caching happens at the build-action level rather than for one entire repository build, a build can reuse some packages while rebuilding only the parts whose inputs changed.
Schematic example: say a first run of go build ./... needs to compile a package whose action is not yet present in the Remote Cache:
go build ./...
Build action inputs
+----------------------+
| Go source files |
| dependency inputs |
| compiler/toolchain |
| build flags |
| relevant environment |
| ... |
+----------+-----------+
|
v
Go computes ActionID
from the action inputs
|
v
+----------------------+
| GOCACHEPROG |
| (platacard/cacheprog)|
+----------+-----------+
|
v
GET remote cache entry
for ActionID a3f9...c2
|
v
+----------------------+
| BuildFetch Cache |
| key: a3f9...c2 |
| status: MISS |
+----------+-----------+
|
v
Compile / link action
|
v
Produce output + OutputID
|
v
GOCACHEPROG uploads output
to BuildFetch CacheLater, the same build action on another machine can produce the same ActionID.
platacard/cacheprog finds the corresponding object in Remote Cache, restores it locally, and Go can skip executing that action:
go build ./... (same action inputs on another machine)
Inputs unchanged
source · dependencies · toolchain · flags · environment
|
v
Same ActionID: a3f9...c2
|
v
+----------------------+
| GOCACHEPROG |
+----------+-----------+
|
v
GET remote cache entry
for ActionID a3f9...c2
|
v
+----------------------+
| BuildFetch Cache |
| key: a3f9...c2 |
| status: HIT |
+----------+-----------+
|
v
Download cached output
|
v
Restore output locally
|
v
Skip expensive action
Build graph continues soonerThe Go Build Cache can also reuse successful package test results in supported go test scenarios.
Go provides debugging options such as GODEBUG=gocachehash=1 and GODEBUG=gocachetest=1 for investigating cache behavior.
How platacard/cacheprog connects Go to BuildFetch Cache
There are two protocols involved:
+----------------------+
| Go command |
| go build / go test |
+----------+-----------+
|
| GOCACHEPROG
| JSON get / put protocol
v
+----------------------+
| platacard/cacheprog |
+----------+-----------+
|
| HTTP remote storage protocol
| GET / PUT cache objects
v
+----------------------+
| BuildFetch Cache |
+----------------------+Go starts the command configured in GOCACHEPROG as a child process and communicates with it using JSON messages over stdin and stdout.
A get operation looks up an ActionID. A put operation supplies the ActionID, OutputID, and the resulting cache data.
platacard/cacheprog translates those operations to its configured remote storage backend.
With its HTTP backend, individual cache entries are addressed with requests such as:
GET /cache/<action-id>
PUT /cache/<action-id>The HTTP protocol also transports metadata associated with the cache entry, including its OutputID.
platacard/cacheprog uses local disk as the staging area required by the Go GOCACHEPROG protocol and can compress remotely stored cache objects.
BuildFetch implements this HTTP storage protocol directly, so platacard/cacheprog can point its HTTP storage URL at a BuildFetch Cache Project.
Share Go Build Cache Across Machines
Go's default
GOCACHEis local to one machine.To reuse those build outputs on different CI agents, engineer workstations, and AI agent environments, configure
GOCACHEPROGwith a remote-capable implementation such asplatacard/cacheprog.BuildFetch Cache natively implements the
platacard/cacheprogHTTP backend and acts as the shared remote storage for those Go cache objects.
A Remote Go Build Cache lets teams share build outputs across engineer workstations, CI, and AI agent environments.
CI, having a more reproducible and controlled environment, typically both reads from and writes to the shared Go Build Cache. Engineers and AI agents can use read-only access to reuse those outputs without publishing new cache entries.
That keeps the cache warm from reproducible CI builds while reducing repeated compilation and other build work across machines.
Unlike copying or archiving an entire GOCACHE directory between CI runs, platacard/cacheprog lets Go retrieve the individual objects it actually requests.
Go only reuses a cached result when the corresponding action identity matches.
For high cache hit rates across machines, keep the Go toolchain, build flags, source and dependency inputs, target platform, and relevant build environment consistent.
cgo note: the Go Build Cache does not automatically detect every change to external C libraries imported through cgo. If external C libraries change, ensure affected Go outputs are rebuilt rather than relying on stale cached results.
The Go Build Cache is also separate from the downloaded Go module source cache.
GOCACHEPROG is concerned with build and test cache objects. Module download caching should be managed separately when needed.
Alternative: Bazel Remote Cache with rules_go
Another way to get Remote Build Cache for Go is to build Go projects with Bazel using rules_go.
rules_go provides Bazel rules for building Go libraries, binaries, and tests, including go_library, go_binary, and go_test.
In this setup, Bazel manages the build graph and caching rather than the Go toolchain's GOCACHE / GOCACHEPROG mechanism.
Both approaches allow Go build work to be shared across machines:
- Go Build Cache +
platacard/cacheprogkeeps builds using the standardgo build/go testworkflow and extends the Go toolchain's native Build Cache with remote storage. - Bazel +
rules_gobuilds the Go project through Bazel and uses Bazel Remote Cache for the resulting build actions.
Choose the approach that matches how the project is built.
Projects using the standard Go toolchain can use platacard/cacheprog, while projects already built with Bazel can use BuildFetch's native Bazel Remote Cache support directly.
Cached Go Build Example
After CI populates the Go Remote Build Cache, a build on a fresh machine, AI agent, or ephemeral CI agent can retrieve many unchanged build actions from BuildFetch.
For example, configure platacard/cacheprog to use the BuildFetch HTTP endpoint:
export BUILDFETCH_CACHEPROG_TOKEN="<generated-token>"
export CACHEPROG_REMOTE_STORAGE_TYPE="http"
export CACHEPROG_HTTP_STORAGE_BASE_URL="https://cache.region.buildfetch.com/project-id/gocacheprog"
export CACHEPROG_HTTP_STORAGE_EXTRA_HEADERS="Authorization:Bearer ${BUILDFETCH_CACHEPROG_TOKEN}"
export GOCACHEPROG="/usr/local/bin/cacheprog"First build, where CI encounters cache misses and populates BuildFetch Cache:
$ time go build ./...
... compile uncached packages ...
... upload generated cache objects through cacheprog ...
real 10m4sA subsequent build with matching inputs on another machine can retrieve those individual outputs from BuildFetch rather than repeating the expensive work:
$ time go build ./...
... cacheprog retrieves matching build objects from BuildFetch ...
real 4sThe timings above are illustrative.
Actual performance depends on the project, amount of parallel work, cache hit ratio, network latency, and size of the cache objects.
Normal go build output is often quiet on success, so individual cache hits may not be obvious from standard build output.
For troubleshooting, platacard/cacheprog logging and Go's GODEBUG cache diagnostics can be used to inspect remote operations and cache hash behavior.
When Go Remote Build Cache helps most
Remote Go Build Cache is especially valuable in ephemeral, autoscalable CI environments, where CI agents are regularly recreated without durable local GOCACHE state.
It also helps large Go repositories and Monorepos where many packages are compiled repeatedly across branches, pull requests, CI jobs, engineer workstations, and AI coding-agent environments.
CI can continuously warm the shared BuildFetch Cache as the codebase evolves.
Other machines then reuse unchanged package and build-action outputs rather than recompiling everything from a cold local cache.
The benefit is highest when builds contain substantial reusable work and environments are sufficiently consistent to generate matching cache ActionIDs.
Configure Go Build Cache
Before setting up Remote Go Build Cache, ensure you have created a BuildFetch Project and Token(s).
platacard/cacheprog: https://github.com/platacard/cacheprogOfficial Go Build Cache documentation: https://go.dev/cmd/go/#hdr-Build_and_test_caching.
BuildFetch Project Cache Setup will provide the HTTP cache URL and generated Token required by cacheprog.
platacard/cacheprog uses the following configuration for its HTTP backend:
CACHEPROG_REMOTE_STORAGE_TYPE=httpCACHEPROG_HTTP_STORAGE_BASE_URLCACHEPROG_HTTP_STORAGE_EXTRA_HEADERSGOCACHEPROG, which tells Go how to launch theplatacard/cacheprogexecutable
The HTTP backend supports additional request headers, allowing the BuildFetch Token to be supplied through an Authorization header.
Generate Tokens
We recommend generating a cache:readwrite Token for CI and cache:readonly Token(s) for engineer and AI agent machines.
Generally, there are two ways to manage engineer Tokens:
- For simpler setups, issuing and rotating a single
cache:readonlyToken could be sufficient. - For precise access control, each engineer should register in BuildFetch, then issue and rotate their own individual
cache:readonlyToken(s).
Generating cache:readwrite Tokens requires Project/Org Admin scope.
For Open Source Projects, we recommend not storing a cache:readonly Token in publicly accessible code because it could lead to misuse and unintended exhaustion of monthly Project limits.
Keep generated Tokens in your CI secret store or local credential environment; do not commit them to source control.
Install platacard/cacheprog
Install a recent platacard/cacheprog release on each machine that will use the Remote Cache.
For CI, using a prebuilt release or including the binary in your CI image avoids rebuilding the cache helper itself on every job.
The binary only needs to be available to the command configured in GOCACHEPROG:
export GOCACHEPROG="/usr/local/bin/cacheprog"platacard/cacheprog supports multiple remote storage backends.
For BuildFetch Cache, use the native HTTP backend.
Configure CI with read-write cache access
On CI, configure the BuildFetch endpoint and a cache:readwrite Token:
export BUILDFETCH_CACHEPROG_TOKEN="<generated-readwrite-token>"
export CACHEPROG_REMOTE_STORAGE_TYPE="http"
export CACHEPROG_HTTP_STORAGE_BASE_URL="https://cache.region.buildfetch.com/project-id/gocacheprog"
export CACHEPROG_HTTP_STORAGE_EXTRA_HEADERS="Authorization:Bearer ${BUILDFETCH_CACHEPROG_TOKEN}"
export GOCACHEPROG="/usr/local/bin/cacheprog"
go build ./...cacheprog receives Go's cache lookups and writes through GOCACHEPROG, retrieves existing objects from BuildFetch on hits, and uploads newly produced objects on misses.
You can use the same configuration with cacheable Go test operations:
go test ./...Configure engineers and AI agents with read-only access
For engineer workstations and AI agents, use a cache:readonly BuildFetch Token.
platacard/cacheprog supports disabling remote cache writes, allowing these environments to consume CI-produced cache entries without publishing new ones.
export BUILDFETCH_CACHEPROG_TOKEN="<generated-readonly-token>"
export CACHEPROG_REMOTE_STORAGE_TYPE="http"
export CACHEPROG_HTTP_STORAGE_BASE_URL="https://cache.region.buildfetch.com/project-id/gocacheprog"
export CACHEPROG_HTTP_STORAGE_EXTRA_HEADERS="Authorization:Bearer ${BUILDFETCH_CACHEPROG_TOKEN}"
export GOCACHEPROG="/usr/local/bin/cacheprog --disable-put"
go build ./...This gives the typical BuildFetch cache topology:
+----------------------+
| BuildFetch Cache |
| shared Go objects |
+----------+-----------+
^
|
read + write | read only
+----------+----------+
| |
+-------+-------+ +-------+-------+
| CI agents | | Engineers |
| cacheprog | | cacheprog |
| read-write | | --disable-put |
+---------------+ +---------------+
^
|
+------+------+
| AI agents |
| read-only |
+-------------+CI populates BuildFetch from reproducible builds while engineers and AI agents reuse those cached results across machines.
Troubleshooting Go cache hits
Go includes several build-cache debugging options:
# Print the inputs that contribute to Go cache hashes.
GODEBUG=gocachehash=1 go build ./...
# Debug Go test cache decisions.
GODEBUG=gocachetest=1 go test ./...Go also provides:
GODEBUG=gocacheverify=1 go build ./...gocacheverify bypasses normal cache reuse while checking cached results against freshly computed outputs.
These debugging options can produce substantial output and are best used for cache investigation rather than normal builds.