Essential Crates Best Practices
A condensed summary of dependency habits that keep Rust codebases fast to build, safe to upgrade, and easy to onboard.
-
Default to serde + one format crate:
serdeat boundaries; addserde_jsonortomlonly where needed. Avoidserde_json::Valuein domain cores. -
Standardize on Tokio for async IO: Mixing runtimes multiplies bugs. Bridge legacy
logwithtracing-log. -
Split errors by crate role:
thiserrorin libraries,anyhowin binaries. Never leakanyhow::Errorfrom published crates. -
Reuse HTTP and DB clients: One
reqwest::Clientand onesqlx::PgPoolper process viaLazyLockor Axum state. -
Pick chrono or time, not both: Document the choice in workspace
READMEand enforce in review. -
Use clap derive for user-facing CLIs: Stable flag names; add aliases before removing old flags.
-
Reach for rayon only past thresholds: Parallelism has overhead; benchmark small inputs first.
-
Prefer LazyLock over custom static mut: On Rust 1.80+, std lazy statics reduce
once_cellsurface. -
DashMap is a cache, not a database: Add eviction and persist authoritative state elsewhere.
-
Enable
rustlsTLS features by default: OpenSSL only when platform or compliance requires it. -
Run
cargo deny checkin CI: License, advisory, and duplicate version gates catch supply-chain risk early. -
Read docs.rs examples before adopting: Crates with runnable examples age better than README-only projects.
-
Minimize feature flags on heavy crates:
tokio = { features = ["rt-multi-thread", "macros", "time"] }beatsfullwhen size matters. -
Keep workspace dependency versions unified:
[workspace.dependencies]in rootCargo.tomlprevents version splits. -
Commit
Cargo.lockfor binaries: Libraries may omit; applications and deployable services must lock. -
Record MSRV in
Cargo.toml:rust-version = "1.97"sets contributor expectations. -
Avoid pre-1.0 crates in core paths without pin:
0.xsemver allows breaking changes; fork risk assessment required. -
Wrap external types in newtypes: Domain modules should not re-export vendor error types blindly.
-
Schedule quarterly dependency hygiene:
cargo update,cargo outdated, and a focused PR fixing advisories. -
Cross-link skills and deep sections: Essential crate pages are indexes; authoritative detail lives in topic sections.
FAQs
How many dependencies is too many?
Count matters less than depth and maintenance. Ten focused crates beat one unmaintained mega-crate.
When to vendor or fork?
When upstream is abandoned and crate is security-critical. Document fork policy in ADR.
Should we allow Git dependencies?
Only temporarily with ticket to publish or return to crates.io version.
Polars in every project?
Add when dataframe analytics are core. Do not pull Polars for simple CSV parsing.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.