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.
- Curated, versioned “metalibraries” or blessed namespaces (e.g.
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.
- Tools:
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.