Workspaces
A Cargo workspace is a set of crates built together with one shared Cargo.lock, unified dependency versions, and single-command test/build workflows.
Busca en todas las páginas de la documentación
A Cargo workspace is a set of crates built together with one shared Cargo.lock, unified dependency versions, and single-command test/build workflows.
# Cargo.toml (workspace root)
[workspace]
members = ["crates/api", "crates/cli", "crates/domain"]
resolver = "2"
[workspace.dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }# crates/api/Cargo.toml
[package]
name = "api"
version = "0.1.0"
edition = "2024"
[dependencies]
domain = { path = "../domain" }
serde = { workspace = true }
tokio = { workspace = true }When to reach for this: Multiple related crates (API, CLI, shared domain) that release and test together.
my_workspace/
├── Cargo.toml
├── Cargo.lock
├── crates/
│ ├── domain/
│ ├── api/
│ └── cli/
└── .cargo/config.toml
cargo build --workspace
cargo test -p domain
cargo run -p cli -- --helpWhat this demonstrates:
Cargo.lock at the root pins versions for all members-p selects a single member packageresolver = "2" is the modern feature resolver (default for edition 2021+)| Pattern | Layout |
|---|---|
| Flat members | api/, cli/ at repo root |
crates/ dir | crates/api, crates/domain |
| Nested | Only when a member is not the root |
[workspace.package]
edition = "2024"
rust-version = "1.97"
license = "MIT OR Apache-2.0"
[workspace.dependencies]
axum = "0.8"Members inherit with:
[package]
name = "api"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = trueA root Cargo.toml with [workspace] only (no [package]) is a virtual workspace. Common for monorepos that ship multiple binaries and libraries.
cargo publish on a member must replace path with version deps. Fix: use cargo publish --dry-run and crates.io metadata checks.core crate.cargo test --workspace --all-targets.| Alternative | Use When | Don't Use When |
|---|---|---|
| Single crate + modules | App fits in one binary | Independent publish/version cycles needed |
| Multiple repos | Teams own release cadence | Shared types change daily |
| Bazel / Nx orchestration | Polyglot monorepo | Pure Rust teams with Cargo-native workflows |
Enough to express boundaries (domain, adapters, binaries), not so many that every one-line change rebuilds the world. Split when compile graphs hurt iteration.
Lists crates cargo build runs when invoked at the root without -p. Useful when the root is virtual.
Yes per [package] edition, but aligning on 2024 reduces cognitive load.
Use exclude = ["tools/experimental"] in [workspace] or simply omit it from members.
At the workspace root. Members do not get their own lockfiles.
Path deps ignore version for resolution; still bump semver on published internal crates if external consumers exist.
cargo clippy --workspace --all-targets -- -D warnings is the standard CI invocation.
Feature resolver version 2 avoids activating features on targets that are not built (e.g. dev-deps on unused platforms).
Extract logic to a small internal crate or copy minimal scripts; Cargo does not share build.rs across members automatically.
Modules are free but compile as one unit. Workspace crates enforce API boundaries and parallel compilation.
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+.
Revisado por Chris St. John·Última actualización: 16 jul 2026