When one package isn't enough — a project with a library, a CLI, and shared internal crates — you reach for a workspace: multiple related packages built and versioned together.
What a workspace is
A workspace is a top-level Cargo.toml with a [workspace] section listing member packages. They share one Cargo.lock and one target/ build directory, so dependencies are resolved once and compiled artifacts are shared. cargo build at the root builds every member.
Why split into a workspace
Splitting a large project into focused crates within a workspace gives you faster incremental builds (only changed crates recompile), clear internal boundaries (a crate's pub API is its contract to its siblings), and the ability to publish some crates while keeping others private. It's how non-trivial Rust projects are organized.
Modules within, crates across
The mental model: use modules to organize code within a crate, and crates (within a workspace) to organize across compilation and publication boundaries. A crate that grows too large to reason about is the signal to split it; a tangle of tightly-coupled crates is the signal you split too early. Balance is the skill.