Dependency Management
Healthy Rust projects pin reproducible dependency graphs, update deliberately within semver, and audit for known vulnerabilities.
Search across all documentation pages
Healthy Rust projects pin reproducible dependency graphs, update deliberately within semver, and audit for known vulnerabilities.
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.
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 update refreshes Cargo.lock, not necessarily Cargo.toml version requirementscargo tree -i finds reverse dependencies (who pulls in openssl?)cargo audit matches lockfile against RustSec advisory DBcargo-deny enforces license and dependency policies in CI| 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 neededcargo tree --edges normal --depth 2
cargo udeps # unused deps (nightly tool)[workspace.dependencies] keeps versions alignedcrates.io (default)cargo update automation with CI gatescargo update without CI - breaks builds on fresh clones until lock committed. Fix: always commit lockfile changes with passing tests.syn majors inflate compile time. Fix: cargo tree -d and unify via dependency bumps or [patch].cargo audit job.cargo update -p affected immediately.rev, tag, or branch with locked commit in lockfile.| 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 |
No, only Cargo.lock (unless you use tools that edit manifests). Bump requirements in Cargo.toml manually when adopting new major versions.
Rarely desirable. For apps, commit Cargo.lock. For exact pins, use = version requirements per crate.
crates.io marks broken releases as yanked; new resolves avoid them but existing lockfiles may still reference until updated.
Document in ADR, set cargo deny to warn, and schedule unification. Some proc-macro stacks temporarily need two syn versions.
For unreleased patches only. Prefer crates.io releases with semver for production services.
Weekly minor/patch refresh with CI; major upgrades planned with changelog review and dedicated PR.
MIT OR Apache-2.0 dual license is standard. Run cargo deny check licenses before shipping commercial products.
Delete from Cargo.toml, cargo build to refresh lock, and grep codebase for imports.
Yes: Dependabot, Renovate, or scripted cargo update PRs with cargo test --workspace gate.
You may need cargo update -p transitive or [patch] until upstream releases a fix. Track RustSec IDs in incident notes.
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+.
Reviewed by Chris St. John·Last updated Jul 16, 2026