Skip to content

ADR 19: Rust Build Optimization

Status: Accepted Date: 2026-04-26

Context

As the Substratum project grows, compiling the Rust workspace (crates/* and apps/*) becomes increasingly slow, particularly during local Docker development. The default Linux linker used in our Debian containers is inefficient, and compiling third-party dependencies takes unnecessary time when Docker containers are spun up from scratch.

We need a stable, performant build pipeline that leverages fast Rust compilation techniques. While we use Nx for the monorepo orchestration, we are currently deferring full native Nx Rust integration (e.g., custom project.json targets) until our CI/CD pipeline is built. For now, our primary focus is optimizing the local developer experience exclusively inside Docker containers running Debian.

Decision

We are implementing a multi-tiered build optimization strategy composed of Cargo configuration tuning:

  1. Linker and Caching (.cargo/config.toml & Docker):

    • For Docker containers (e.g., our debian:bookworm-slim images), the build runs in a Linux environment. We explicitly configure Cargo to use the fast LLVM linker (lld) for Linux target triples (x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu) to significantly speed up the linking phase of compilation.
    • We require sccache as the rustc-wrapper to provide persistent, cross-branch caching of compiled Rust artifacts.
    • For Docker (Dockerfile.gateway), sccache, lld, and clang are installed in the build container, and the cache is persisted to the host via named volumes (sccache_data mapped to /var/cache/sccache, gateway_target mapped to /app/target, and cargo_registry mapped to /usr/local/cargo/registry).
  2. Dependency Optimization (Cargo.toml):

    • We removed previous experimental overrides for opt-level = 3 on third-party dependencies. While opt-level = 3 provides significantly faster runtime execution for cryptographic operations and networking during local testing, it caused initial Docker volume population to take upwards of 20 minutes. We favor fast developer onboarding and iteration (opt-level = 0) combined with persistent Docker volumes.

Consequences

  • Positive:
    • Massive reduction in incremental build times due to lld and sccache. Subsequent Docker rebuilds are nearly instantaneous.
    • Complete stability; no crashing daemons caused by third-party plugins.
    • Initial Docker builds are extremely fast (1-2 minutes) by keeping opt-level = 0 and persisting volumes.
  • Negative:
    • Local execution of the Gateway and Sidecar will be noticeably slower (especially cryptographic hashing) compared to production due to the lack of dependency optimizations in the dev profile.