What is a remote cache?
A remote cache (also called a remote build cache) is shared storage for the outputs of build tasks, keyed by a hash of everything that went into producing them. When your build tool is about to run a task - compile a package, run a test suite, lint a project - it first computes that hash and asks the cache: has anyone, on any machine, already run this exact work? If yes, it downloads the stored outputs and replays them in milliseconds. If no, it runs the task and uploads the result so the next machine gets the hit.
The core idea is simple: the same inputs always produce the same outputs, so identical work should only ever be done once - across the whole team, not just per machine. A monorepo with fifty projects rarely changes more than a few of them per commit; everything downstream of unchanged code is, by definition, work someone has already done. A remote cache turns that observation into saved minutes on every build.
The terms remote caching, remote build cache, and distributed build cache all describe the same mechanism. Nx calls it the remote cache, Lerna delegates it to Nx, Turborepo calls it Remote Caching, Bazel calls it a remote cache, and Gradle calls it the remote build cache - the protocol details differ, the concept does not.
How remote caching works
Every remote cache implementation follows the same four-step loop:
- 1. Hash the inputs. The build tool computes a cache key from the complete set of inputs to a task: the source files it reads, the resolved dependencies, the command and its flags, the toolchain version, and any environment variables that affect the output. Change any input and the key changes.
- 2. Look up the key. The tool sends the key to the cache server - typically a
GETover HTTPS with an auth token. A hit returns the stored artifact; a miss returns a 404. - 3. Restore or run. On a hit, the tool unpacks the artifact - output files, plus the recorded terminal output so the replayed task looks exactly like a real run. On a miss, the task simply executes as it would without any cache.
- 4. Upload the result. After a miss, the freshly built outputs are uploaded under the computed key, so every subsequent machine with the same inputs gets a hit.
Because the key is a content hash of the inputs, there is no invalidation logic to get wrong: stale entries are never served, they are simply never looked up again, because changed inputs produce a different key. This is what separates a build cache from the hard cache-invalidation problems of application caching - correctness falls out of the keying scheme. (What belongs in the key, and how under- and over-keying break caches, is covered in depth in What makes a good build cache.)
Local cache vs remote cache
Most build tools with caching ship a local cache first: results are stored on the machine that produced them, so re-running an unchanged task on the same machine is instant. That alone is valuable, but its blind spot is everything that is not your machine:
- CI runners usually start clean. An ephemeral runner has an empty local cache on every job, so it rebuilds the world - even when the previous pipeline built the exact same code minutes earlier.
- Teammates repeat each other's work. When a colleague builds a branch you then check out, your machine has none of their results.
- Fresh clones and new machines start from zero. Onboarding builds are always cold.
A remote cache removes the blind spot by making the cache a shared, network-accessible service. The first build of any given input state is done once, by whoever happens to run it first - a developer or a CI job - and everyone else replays it. The biggest single win is usually CI: a warm remote cache means a pull-request pipeline only truly executes the tasks affected by the diff.
Remote cache vs CI cache vs artifact storage
"Cache" is an overloaded word in CI, and three different mechanisms get conflated. They solve different problems and are usually complementary, not alternatives:
| Mechanism | What it stores | Keyed by | Scope |
|---|---|---|---|
| Remote build cache | Per-task outputs (compiled files, test results, terminal output) | Fine-grained content hash of each task's inputs | Every machine: CI and developer laptops |
| CI cache (e.g. actions/cache) | Whole directories (node_modules, ~/.gradle, build dirs) | Coarse keys you write by hand (often a lockfile hash) | The CI provider only; developers never benefit |
| Artifact storage | Final deliverables (binaries, images, reports) for humans and deploys | A name and a run/version, not content hashes | Consumers of the build, not the build itself |
A CI cache like GitHub Actions' actions/cache is great at what it does - skipping npm install by restoring node_modules - but it cannot skip the build itself: it has no notion of tasks, no dependency graph, and its coarse keys either miss too often or restore stale directories. A remote build cache sits at a different layer: it skips the compile, test, and lint work task by task, and the same cache serves CI and every developer machine. Most teams end up running both - the CI cache for dependency installs, the remote cache for the actual build graph. For a broader look at where CI time actually goes, see How to improve your CI times. If misses are higher than expected, follow the build cache hit-rate troubleshooting guide.
Which build tools support remote caching
Nx
Nx computes a hash per task from its inputs (source files, dependency outputs, runtime values) and caches the declared outputs. Remote caching uses the official self-hosted remote cache API: point Nx at any conforming server with two environment variables and every nx build, nx test, or nx affected run consults it automatically:
NX_SELF_HOSTED_REMOTE_CACHE_SERVER=https://remote.cachely.dev
NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN=<your token>Getting the hit rate up is mostly about tuning what goes into the hash - see Tuning Nx cache inputs and outputs. For the full Nx-specific picture - the task hash, setup, Nx Cloud vs self-hosted vs managed, and troubleshooting - see the Nx remote cache guide.
If the managed category is the likely fit, the managed remote build cache buyer guide covers protocol compatibility, security, operations, and provider evaluation in depth.
Lerna
Modern Lerna uses Nx for task scheduling and caching. A lerna run therefore honors the same NX_SELF_HOSTED_REMOTE_CACHE_SERVER and NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN variables as a direct Nx command and sends the same Nx artifact format. Mark the relevant targets cacheable in nx.json; no Lerna-specific cache server or protocol is required.
Turborepo
Turborepo speaks the Vercel Remote Cache protocol. Any server implementing it works, configured with TURBO_API, TURBO_TOKEN, and TURBO_TEAM. Artifact signing (signature: true) adds an HMAC so clients verify artifacts were produced by someone holding the signing key. The full setup - hosted, self-hosted, and managed - is covered in the Turborepo remote cache guide.
Bazel
Bazel pioneered remote caching at scale: content-addressed storage over gRPC or HTTP (--remote_cache), plus optional remote execution. Its hermetic, sandboxed action model is the strictest interpretation of the same idea - every action declares its full input set, so keys are precise and hits are trustworthy. The action cache, CAS, HTTP setup, CI security, and backend choices are covered in the Bazel remote cache guide.
Gradle
Gradle's build cache (--build-cache with a remote HTTP backend) caches task outputs the same way. The recommended rollout is a trusted CI build that pushes entries while developer and pull-request builds read them. See the Gradle remote build cache guide for HttpBuildCache setup, FROM-CACHE verification, and troubleshooting.
sccache and others
sccache wraps Rust/C/C++ compilers and stores object files in shared storage. Pants, Buck2, and moon all ship the same mechanism. The pattern is universal enough that the question is rarely "does my tool support it" but "where should the cache live and who operates it".
Security: cache poisoning and read-only tokens
A remote cache is a supply-chain component: whatever is in it gets executed, linked, or shipped by trusted builds. The attack that matters is cache poisoning - an attacker with write access plants a malicious artifact under a key that a trusted build will later look up. For Nx this is not theoretical: CVE-2025-36852 (CREEP) showed that when untrusted pull-request builds share write credentials with trusted builds - the default in most DIY bucket setups - a fork PR can poison the artifact that the main branch build then consumes.
Two properties close the attack, and they are worth demanding from any remote cache setup:
- Read-only tokens for untrusted builds. PR and fork pipelines get tokens that can read (so they stay fast) but never write - enforced server-side, not by convention.
- Immutable, content-addressed artifacts. Once a key exists, writes to it are rejected (409), so a known-good artifact can never be silently replaced.
The full attack walkthrough is in Cache poisoning and CVE-2025-36852, and the trust model Cachely enforces is documented on the security page. One more reassuring property: a remote cache never needs your source code. It stores task outputs and their hashes - there is no repository to connect and no code for the cache operator to see.
Measuring the impact
Two numbers tell you whether a remote cache is paying off:
- Hit rate - the share of task executions served from cache. Healthy monorepos see high rates because most commits touch few projects. A low hit rate usually means over-keying: something volatile (a timestamp, an absolute path, an always-changing env var) is leaking into the hash.
- Time saved - each task's measured cold run time multiplied by how often it was a hit. Sum it and you get the CI minutes (and, at your runner rates, the dollars) the cache returned. Teams with warm caches routinely cut 30-70% off CI wall time.
Whatever cache you run, instrument it - a cache nobody measures quietly decays as inputs drift. The economics of measuring (and what typical savings look like) are worked through in How much can a managed remote cache reduce CI build times?. For a quick what-if model, try the CI savings calculator.
Self-hosted vs managed remote cache
Once you want a remote cache, there are three ways to get one:
- The build tool vendor's platform (Nx Cloud, Vercel). Caching bundled with a broader platform - distributed execution, runners, analytics - typically priced per seat or usage.
- Self-hosted / DIY. An open-source cache server or an object-storage bucket with an adapter. Full control, but you own hosting, scaling, token security, immutability enforcement, monitoring, and upkeep - and DIY bucket setups are exactly where CVE-2025-36852 lived.
- A managed remote cache. A service that implements the tool's open cache protocol and operates the storage, auth, and safety properties for you.
Cachely is in the third category: a managed implementation of the Nx self-hosted remote cache API, the Turborepo remote cache protocol, the Gradle HTTP Build Cache protocol, and the Bazel HTTP remote cache protocol, with read-only tokens and immutable artifacts enforced at the API, hit-rate and ROI reporting built in, and flat pricing with no per-seat fees. The remote build cache comparison lay the options side by side - including vs Nx Cloud, vs a self-hosted Nx cache, and vs Vercel Remote Cache - and the honest answer is that each is right for someone. If you want the cache without the operational load, setup takes about five minutes: the docs walk through it.
Related guides
- Nx remote cacheSet up the official Nx self-hosted cache and see how the task hash works.
- Turborepo remote cacheTURBO_API / TURBO_TOKEN setup, signing, and hosted vs self-hosted options.
- GitHub Actions cache guideactions/cache vs artifacts vs a task-level remote build cache in CI.
- Managed remote build cacheHow to evaluate a managed cache on protocol support, security, and cost.
- Improve cache hit rateDiagnose over-keying, env drift, unstable outputs, and missing outputs.