Dependency Management
Healthy Rust projects pin reproducible dependency graphs, update deliberately within semver, and audit for known vulnerabilities.
Recipe
cargo update -p serde
cargo tree -i openssl
cargo audit
cargo deny checkWhen to reach for this: Weekly maintenance, before releases, or after a security advisory.
Working Example
Workspace maintenance workflow:
# See what would change
cargo update --dry-run
# Bump one crate within semver bounds in Cargo.lock
cargo update -p tokio
# Find why a crate is in the graph
cargo tree -i ring
# Security scan (install: cargo install cargo-audit)
cargo audit
# License + ban + duplicate detection
cargo deny check# deny.toml (excerpt)
[bans]
multiple-versions = "warn"
[sources]
unknown-registry = "deny"What this demonstrates:
cargo updaterefreshesCargo.lock, not necessarilyCargo.tomlversion requirementscargo tree -ifinds reverse dependencies (who pulls inopenssl?)cargo auditmatches lockfile against RustSec advisory DBcargo-denyenforces license and dependency policies in CI
Deep Dive
Semver in Practice
| Change | Bump |
|---|---|
| Bug fix, same API | PATCH |
| New backward-compatible API | MINOR |
| Breaking public API | MAJOR |
serde = "1.0.210" # allow compatible 1.0.x
my_lib = "=2.1.0" # exact pin when neededMinimizing the Graph
cargo tree --edges normal --depth 2
cargo udeps # unused deps (nightly tool)- Remove unused features to drop transitive crates
- Prefer crates with few dependencies for security surface
- Workspace
[workspace.dependencies]keeps versions aligned
Supply Chain Hygiene
- Pin registry to
crates.io(default) - Review new deps: maintenance, unsafe usage, bus factor
- Enable Dependabot or
cargo updateautomation with CI gates
Gotchas
cargo updatewithout CI - breaks builds on fresh clones until lock committed. Fix: always commit lockfile changes with passing tests.- Ignoring duplicate versions - two
synmajors inflate compile time. Fix:cargo tree -dand unify via dependency bumps or[patch]. - Audit only on release - advisories land mid-sprint. Fix: weekly
cargo auditjob. - Yanked crate panic - old lockfiles may reference yanked versions. Fix:
cargo update -p affectedimmediately. - Git deps without rev - floating branch breaks reproducibility. Fix: pin
rev,tag, orbranchwith locked commit in lockfile.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
cargo-outdated | See available newer versions | You need lockfile-only refresh |
[patch.crates-io] | Emergency fork | Long-term dependency strategy |
Vendor dir (cargo vendor) | Air-gapped builds | Normal internet-connected CI |
FAQs
Does cargo update change Cargo.toml?
No, only Cargo.lock (unless you use tools that edit manifests). Bump requirements in Cargo.toml manually when adopting new major versions.
How do I pin all dependencies exactly?
Rarely desirable. For apps, commit Cargo.lock. For exact pins, use = version requirements per crate.
What is a yanked crate?
crates.io marks broken releases as yanked; new resolves avoid them but existing lockfiles may still reference until updated.
How do I allow duplicate versions temporarily?
Document in ADR, set cargo deny to warn, and schedule unification. Some proc-macro stacks temporarily need two syn versions.
Should I use git dependencies?
For unreleased patches only. Prefer crates.io releases with semver for production services.
How often should I update?
Weekly minor/patch refresh with CI; major upgrades planned with changelog review and dedicated PR.
What licenses are common?
MIT OR Apache-2.0 dual license is standard. Run cargo deny check licenses before shipping commercial products.
How do I remove a dependency?
Delete from Cargo.toml, cargo build to refresh lock, and grep codebase for imports.
Can I automate updates?
Yes: Dependabot, Renovate, or scripted cargo update PRs with cargo test --workspace gate.
How do advisories affect transitive deps?
You may need cargo update -p transitive or [patch] until upstream releases a fix. Track RustSec IDs in incident notes.
Related
- Cargo.toml Explained - version syntax
- Workspaces - shared dependency tables
- Supply Chain Security - broader policy
- Cargo Best Practices - maintenance checklist
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+.