Skip to content

Flywheel

Main

Flywheel is a disk-backed build cache and package proxy for CI workloads. It stores build outputs and downloaded dependencies on local disk using an embedded RocksDB metadata store. No external database or object store is required.

Capabilities

Workload Interface
Go build outputs GOCACHEPROG through flywheel cacheprog
Bazel HTTP remote action cache and CAS
Go modules GOPROXY
Python packages Simple Repository API with HTML and JSON negotiation
JavaScript packages npm install metadata and tarballs
Rust packages Cargo sparse registry mirror
Other build tools Generic HTTP key/value cache
Artifact pipelines SHA-256 artifacts and mutable references

Runtime model

  • Each replica owns one local data directory.
  • Cached data is not replicated and has no remote storage tier.
  • Disk loss, shard replacement, and shard membership changes produce cache misses.
  • Raw artifacts and Bazel CAS writes are crash-durable on the accepting disk.
  • Generic build-cache, Bazel action-cache, and package-proxy entries are best effort.
  • Channels provide cache isolation, access policy, retention, and deletion lifecycle.
  • The optional routing agent distributes Default Channel traffic across independent shards.

Flywheel is a cache, not a system of record. Every client must be able to regenerate or refetch missing data.

Local execution

Requirements

  • Stable Rust toolchain with Rust 2024 edition support
  • Clang and libclang
  • CMake
  • C++ compiler

Start a replica

make build
mkdir -p /tmp/flywheel-data
./target/debug/flywheel serve --data-dir /tmp/flywheel-data

The default listener is 127.0.0.1:8080. SIGINT performs a graceful shutdown. Reusing the data directory preserves cached data between runs.

Verify the cache

curl --fail --silent --show-error http://127.0.0.1:8080/health/ready

printf 'hello from flywheel\n' >/tmp/flywheel-demo
curl --fail --silent --show-error \
  --request PUT \
  --data-binary @/tmp/flywheel-demo \
  http://127.0.0.1:8080/build-cache/http/demo
curl --fail --silent --show-error \
  http://127.0.0.1:8080/build-cache/http/demo

Client configuration

The following examples use the open Default Channel on a local replica.

Go build cache

export GOCACHEPROG='flywheel cacheprog --url http://127.0.0.1:8080/build-cache/http/'
go build ./...

cacheprog maintains a verified local object cache and supports session-based prefetching: it fetches the session manifest with one plain cache GET of its derived key and warms its local cache with bounded parallel cache GETs, one per distinct output. Against replicated shards, prefetch requires a pod-local flywheel agent sidecar, which routes the manifest GET and each download to the shard that owns it. Use --ephemeral-cache to prevent reuse by later processes. Persistent local directories and Kubernetes hostPath mounts are documented in the cacheprog operations guide.

Bazel

build --remote_cache=http://127.0.0.1:8080/build-cache/bazel

This setting belongs in .bazelrc. Bazel CAS bodies use durable publication. Action-cache entries use best-effort publication.

Package managers

export GOPROXY=http://127.0.0.1:8080/proxy/go
export PIP_INDEX_URL=http://127.0.0.1:8080/proxy/python/simple/
export NPM_CONFIG_REGISTRY=http://127.0.0.1:8080/proxy/npm/

Cargo source replacement in .cargo/config.toml:

[source.crates-io]
replace-with = "flywheel"

[source.flywheel]
registry = "sparse+http://127.0.0.1:8080/proxy/cargo/index/"

Package proxies are read-only. Missing packages are fetched from the configured upstream, cached locally when capacity permits, and returned through the same channel.

Authentication, fallback behavior, custom channels, and protocol-specific configuration are covered in the client operations guide.

Channels

A channel is the isolation and lifecycle boundary for cached data.

Channel type Access Intended use
Default Open Shared cache protected by the deployment network boundary
Open custom Open Separate retention and cleanup without application credentials
Protected Token Separate retention and cleanup with application authentication

Access type is fixed at channel creation. Retention can be changed later. Deletion fences new writes, removes cached data, and resumes after restart if interrupted. Protected channel tokens are returned once and cannot be recovered or rotated.

Flywheel serves plain HTTP. TLS termination and registry-level access control belong at the deployment boundary. Detailed procedures are in channel administration.

Kubernetes

The Helm chart deploys persistent shards, a headless discovery Service, and an optional shared routing-agent tier.

helm upgrade --install flywheel charts/flywheel \
  --namespace cache \
  --create-namespace

Requirements and defaults:

  • Kubernetes 1.32 or newer
  • One ReadWriteOncePod volume per shard
  • Retained claims on scale-down and chart deletion
  • Non-root containers with read-only root filesystems
  • Startup, readiness, and liveness probes
  • PodDisruptionBudgets and topology spreading

Production deployments must pin the image digest, select a StorageClass, and size cache watermarks against each shard volume.

Topology Routing
Shared agent Agent Deployment and ClusterIP Service managed by the chart
Pod-local agent Agent sidecar in each build Pod; chart manages shards and discovery

The routing agent currently serves the Default Channel only. Custom channels remain on a single-replica boundary until a shared channel control plane exists.

Deployment values and rollout constraints are documented in the Helm chart guide. The complete sidecar manifest is in the sidecar runbook.

Development

make ci
make release

make ci checks formatting, runs Clippy with warnings denied, and executes the test suite. Pull requests and pushes to main run the same gates in GitHub Actions.

See BUILDING.md for platform prerequisites and troubleshooting. Contributions are welcome under the process in CONTRIBUTING.md.

Documentation

Document Contents
Architecture Publication, storage, channels, eviction, package rewriting, and scaling boundaries
Operations Configuration, clients, capacity, metrics, recovery, Helm, and sidecars
Helm chart Storage, scheduling, security, networking, monitoring, and values
Domain language Channel terminology and invariants
Recency-aware eviction ADR Retention and eviction decision record

Community and license

Participation is governed by the Code of Conduct. Use SUPPORT.md for support and issue-reporting guidance and SECURITY.md for private vulnerability reporting.

Flywheel is licensed under the Apache License 2.0.

Releases

Packages

Used by

Contributors

Languages