TL;DR: A Cargo workspace is a directory containing multiple crates (
[[workspace.members]]) that share a singleCargo.lockand build cache. Use workspaces to split a large project into focused crates; acorelibrary, a CLI binary, a web server; while keeping them versioned and compiled together. Runcargo build --workspaceto build all, orcargo build -p crate-namefor one. Define shared dependency versions in[workspace.dependencies]to avoid version drift across crates.
What Is a Cargo Workspace?
A workspace is a set of Rust crates in a single repository that share one Cargo.lock, one build output directory (target/), and coordinated dependency versions.
my-project/
├── Cargo.toml ← workspace root (no [package])
├── Cargo.lock ← shared lock file
├── target/ ← shared build output
├── core/ ← library crate
│ ├── Cargo.toml
│ └── src/lib.rs
├── server/ ← binary crate
│ ├── Cargo.toml
│ └── src/main.rs
└── cli/ ← binary crate
├── Cargo.toml
└── src/main.rsRoot Cargo.toml:
[workspace]
members = ["core", "server", "cli"]
resolver = "2" # always use resolver 2 for feature unificationHow Do You Create a Workspace?
Create a root Cargo.toml with [workspace], then cargo new each member crate.
mkdir my-project && cd my-project
# Create workspace root Cargo.toml
cat > Cargo.toml << 'EOF'
[workspace]
members = ["core", "server", "cli"]
resolver = "2"
EOF
# Create member crates
cargo new core --lib
cargo new server
cargo new cli
# Build everything
cargo build --workspaceHow Do You Share Dependencies Across Crates?
Use [workspace.dependencies] to define versions once; member crates opt in with { workspace = true }.
Root Cargo.toml:
[workspace]
members = ["core", "server", "cli"]
resolver = "2"
[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
sqlx = { version = "0.8", features = ["postgres", "runtime-tokio"] }
thiserror = "2"
anyhow = "1"
tracing = "0.1"Member server/Cargo.toml:
[package]
name = "server"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { workspace = true } # uses version from workspace
serde = { workspace = true }
sqlx = { workspace = true }
core = { path = "../core" } # local crate dependencyAll crates use the same dependency version; no drift, no conflicting lock entries.
How Do You Run Commands on Specific Crates?
# Build all crates
cargo build --workspace
# Build one crate
cargo build -p server
# Test all
cargo test --workspace
# Test one crate
cargo test -p core
# Run a binary from a specific crate
cargo run -p cli -- --help
# Check all without building
cargo check --workspace
# Clippy on all
cargo clippy --workspaceWhat Are the Benefits of a Workspace?
| Benefit | Detail |
|---|---|
Shared Cargo.lock | All crates use identical dependency versions |
| Shared build cache | Compile a crate once, reuse across members |
| Centralized dependency versions | [workspace.dependencies] prevents version drift |
| Clear boundaries | Each crate has its own API, tests, and docs |
| Selective compilation | Build/test only the crate you're working on |
| Publish independently | Release crates separately to crates.io |
Frequently Asked Questions
A workspace is Cargo's implementation of a monorepo for Rust crates. The workspace root is the monorepo root; all Rust crates live under it and share tooling. A monorepo can contain non-Rust code outside the workspace.
Yes; each crate specifies its own edition in its Cargo.toml. But all crates share the same resolver set in the workspace root.
Prefer a "virtual workspace" (root Cargo.toml has [workspace] but no [package]). This keeps the root clean. Only make the root a crate if you have a strong reason (rare).
cargo new new-crate --lib
# Then add "new-crate" to [workspace] members in root Cargo.tomlNo; Cargo does not support nested workspaces. All crates must be listed in the top-level workspace members.
Sources
Related Glossary Terms
- Cargo: The build system workspaces extend
- Module: Modules organize code within a crate; workspaces organize crates
- Feature Flags: Feature unification works differently in workspaces
- Clap: CLI apps often live inside dedicated workspace crates alongside shared libraries
Keep Reading
- Best Way to Learn Rust in 2026: when and how to structure a multi-crate workspace
- Rust 2024 Edition: What's New: workspace-level edition and dependency improvements
- Learn Rust in 2026: workspaces are how real Rust projects are organized
