Rust’s dependencies are starting to worry me

Rust’s dependency explosion vs other ecosystems

  • Many feel Cargo makes it “too easy” to add crates, and that each crate often pulls dozens of transitive deps. Even trying to be conservative still yields very large trees.
  • In Rust, libraries are commonly split into many small crates (partly for compile-time parallelism and reuse, with feature flags for optional pieces).
  • Some compare this to C/C++ where deps appear fewer: either because dynamic/system libraries hide transitive deps, or because build tools (cmake, autotools, pkg-config) are painful enough to discourage them.
  • Others argue C/C++ dependency graphs are just as big, only less visible and often curated by distros.

Standard library vs crates

  • Strong current in favor of a larger, Go-style or Java-style stdlib (or a “second stdlib” / curated meta-library) to reduce random crates: logging, HTTP, serialization, regex, datetime, etc.
  • Counter-arguments:
    • Big stdlibs inevitably accumulate obsolete, inconsistent APIs that are hard to change (examples given from Python, Java, C++).
    • Rust targets many environments (including no_std/embedded), so a fat stdlib is risky and expensive to maintain.
  • Proposed middle grounds:
    • Curated, versioned “metalibraries” or blessed namespaces (e.g. @rust/...) outside core std, tested together and with relaxed stability guarantees.
    • Pointed out that many key crates (regex, glob, etc.) are already maintained under the Rust org.

Supply-chain and security concerns

  • Core worry: projects routinely pull in millions of lines of unaudited code. Unmaintained crates and semver-0 “forever beta” packages exacerbate this.
  • Suggested mitigations:
    • Tools: cargo-audit, cargo-deny, cargo-vet/cargo-crev, cargo-geiger, vendoring plus filters, SBOMs.
    • Organizational: internal mirrors, approval processes per new crate, treating transitive deps as first-class risks.
    • Cultural: copy small functionality instead of adding a crate; prefer “mature” low-churn libs; push authors to use feature flags and Sans-IO patterns.

Async runtimes and ecosystem fragmentation

  • Async is seen by some as locking you into a heavyweight runtime (Tokio), creating de facto “Tokio-Rust” and making async libraries mutually incompatible.
  • Others accept this as a pragmatic winner-take-most outcome and note that large foundations (e.g. the Tokio family) are carefully curated.

Capabilities and sandboxing ideas

  • Several comments argue the long-term fix is capability systems: libraries must declare and be granted specific powers (file I/O, network, unsafe, etc.), enforced statically or at runtime.
  • Prior attempts (Java/.NET sandboxing) largely failed in practice; WASM/WASI, special-purpose languages, and effect systems are mentioned as more promising directions, but retrofitting existing ecosystems is seen as hard.