Rust Learning Path — Chapter 16. Once a Rust program grows beyond a few files, good project structure becomes essential. Rust gives you several related building blocks—modules, crates, packages, and workspaces—that help you organize code without sacrificing compile-time safety.
This chapter explains how those pieces fit together, how visibility works with pub, how use paths simplify imports, how to split code across files, and when a Cargo workspace is the right choice.
1. The terminology first
| Concept | Meaning |
|---|---|
| Module | A namespace inside a crate used to organize items. |
| Crate | The smallest compilation unit in Rust; either a binary crate or library crate. |
| Package | A Cargo project described by one Cargo.toml ; it contains one or more crate targets. |
| Workspace | A group of packages that share a Cargo lockfile and target directory. |
2. Binary and library crates
A project created with cargo new my_app normally starts as a binary crate because Cargo creates src/main.rs.
my_app/ ├── Cargo.toml └── src/ └── main.rsA library project can be created with:
cargo new my_library --libThat creates src/lib.rs. A package may contain both library and binary targets, which is common for real applications: shared business logic stays in the library while the executable only handles startup and wiring.
3. Create modules with mod
Suppose an application has configuration and API logic:
// src/main.rs mod config; mod api; fn main() { let cfg = config::load(); api::start(cfg); }Then create src/config.rs:
pub struct Config { pub port: u16, } pub fn load() -> Config { Config { port: 8080 } }And src/api.rs:
use crate::config::Config; pub fn start(config: Config) { println!("API listening on {}", config.port); }4. Visibility and pub
Rust items are private to their parent module by default. Use pub only where another module really needs access.
pub struct User { pub id: u64, email: String, }Here User and id are public, while email remains private. This lets a module protect its own invariants instead of exposing every field.
5. Absolute and relative module paths
You can refer to an item using a path from the crate root:
use crate::config::Config;Or with a relative path such as super:: when moving to a parent module:
use super::shared::RequestId;For application code, clear absolute paths from crate:: are often easier to understand as the codebase grows.
6. Nested modules and directories
A larger API module might look like:
src/ ├── main.rs ├── api.rs └── api/ ├── users.rs └── health.rssrc/api.rs declares the submodules:
pub mod health; pub mod users;This is a good pattern when one logical module needs several source files.
7. Re-export a clean public API
Re-exporting lets callers use a shorter, more stable path:
// src/lib.rs mod config; pub use config::Config;Consumers can now write:
use my_library::Config;instead of depending on the internal module layout.
8. Multiple binaries
A package can expose several executables under src/bin:
src/ ├── lib.rs └── bin/ ├── api.rs └── worker.rsRun them with:
cargo run --bin api cargo run --bin workerThis is useful when an application has an HTTP server and a background worker sharing the same library.
9. Cargo workspaces
When several related packages should be developed together, use a workspace:
platform/ ├── Cargo.toml ├── api/ │ └── Cargo.toml ├── core/ │ └── Cargo.toml └── worker/ └── Cargo.tomlWorkspace root:
[workspace] resolver = "2" members = ["api", "core", "worker"]Now Cargo can build or test all members together:
cargo build --workspace cargo test --workspace10. Workspace dependencies
Shared dependency versions can be declared centrally:
[workspace.dependencies] serde = { version = "1", features = ["derive"] } tokio = { version = "1", features = ["full"] }Then a member package can inherit them:
[dependencies] serde.workspace = true tokio.workspace = true11. Suggested backend layout
src/ ├── main.rs ├── app.rs ├── config.rs ├── error.rs ├── routes/ │ ├── mod.rs │ ├── health.rs │ └── users.rs ├── services/ │ ├── mod.rs │ └── user_service.rs └── repositories/ ├── mod.rs └── user_repository.rsThe exact folder names matter less than keeping responsibilities clear and dependencies flowing in sensible directions.
12. Common mistakes
- Making everything pub just to silence visibility errors.
- Creating dozens of tiny modules before the code actually needs them.
- Putting all logic in main.rs .
- Using a workspace for a project that only needs one package.
- Exposing internal modules instead of re-exporting a small public API.
13. Mini lab: split an application
Create a project and refactor it into three modules:
cargo new rust_structure_lab cd rust_structure_labCreate config, service, and output modules. Keep fields private where possible, expose only necessary functions, and verify with:
cargo fmt cargo clippy cargo test cargo runKey takeaways
- Modules organize names inside a crate.
- Crates are compilation units.
- A Cargo package contains crate targets.
- Workspaces group related packages and share build artifacts.
- Keep APIs intentionally small with privacy and re-exports.
Join the discussion
0 CommentsAsk questions, add context, or share what worked.
More from Melochip Editorial
Learn what Playwright testing is, why modern QA teams use it, how testers can get started, and the major types...
7 min read · Sep 19, 2026
Learn how Kubernetes Deployments and ReplicaSets work with practical YAML, scaling, self-healing, rolling upda...
7 min read · Sep 17, 2026
Learn Kubernetes security best practices with RBAC, Secrets, ServiceAccounts, Pod securityContext, NetworkPoli...
6 min read · Sep 17, 2026Related articles
Learn Linux from the ground up with simple explanations of the kernel, distributions, filesystem, commands, pe...
4 min read · Updated Oct 1, 2026
Learn what Playwright testing is, why modern QA teams use it, how testers can get started, and the major types...
7 min read · Sep 19, 2026
Learn how Kubernetes Deployments and ReplicaSets work with practical YAML, scaling, self-healing, rolling upda...
7 min read · Sep 17, 2026
Learn Kubernetes security best practices with RBAC, Secrets, ServiceAccounts, Pod securityContext, NetworkPoli...
6 min read · Sep 17, 2026Stay in the loop. Get new Melochip articles
Receive Melochip article updates when new articles are available. Explicit opt-in only.
No comments yet. Start the discussion.