tezvyn:

How do you manage multiple related Rust crates as a single unit?

AI-drafted, machine-checkedSource: doc.rust-lang.orgadvanced

Tests Cargo workspaces for multi-crate Rust projects. Strong answers cite the [workspace] section, shared Cargo.lock, unified target directory, inherited metadata, and workspace-wide commands.

WHAT THIS TESTS: This question probes whether you have operated a Rust monorepo at scale. Interviewers want to see that you understand Cargo workspaces as the native solution for coordinating multiple crates, not just as a configuration detail but as a dependency-resolution and build-efficiency primitive. The underlying concern is whether you can keep builds reproducible, avoid version drift between internal crates, and reduce CI overhead as the project grows.

A GOOD ANSWER COVERS: First, name the [workspace] section in a root Cargo.toml, including the concept of a virtual manifest when there is no root package. Second, explain that all members share a single Cargo.lock, which guarantees that the binary, core library, and client library resolve the same transitive dependency versions. Third, mention the shared target directory, which deduplicates build artifacts and cuts disk usage and incremental compile times. Fourth, describe workspace-level inheritance, such as workspace.package for shared metadata and workspace.dependencies for unified version pins. Fifth, note that commands like cargo check --workspace or cargo test --workspace run across members atomically, and that [patch], [replace], and [profile] sections are enforced only at the root.

COMMON WRONG ANSWERS: A junior-level mistake is suggesting manual path dependencies in each crate without a workspace; this fragments the lockfile and lets crates resolve different versions of the same transitive dependency. Another red flag is proposing git submodules or separate repositories, which destroys the unified build and complicates atomic refactors. Some candidates mention workspaces but forget the shared target directory or the root-only restriction on profiles and patches, which signals they have not debugged a large workspace build.

LIKELY FOLLOW-UPS: An interviewer might ask how you would handle a crate that should not be built by default, which is answered with the exclude list or default-members. They could also ask about resolver versioning, especially the requirement to set resolver explicitly in a virtual workspace because there is no package.edition to infer it from. A third follow-up is how to publish workspace members to crates.io while keeping shared metadata DRY, which touches on workspace inheritance and the publish field.

ONE CONCRETE EXAMPLE: Imagine a workspace with three members: a server binary, a core library, and a client library. Without a workspace, each crate might pull in tokio 1.37, 1.38, and 1.39 respectively, causing type mismatches when passing structures across crate boundaries. With a workspace, the single Cargo.lock pins one tokio version, the shared target directory stores one set of object files, and workspace.dependencies lets you bump tokio once in the root. Running cargo build --workspace from CI then produces a coherent artifact graph in one shot.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.