Project Structure Patterns
Common layouts: single-crate src/lib.rs + main.rs, workspace crates/*, domain modules models/, handlers/, integration tests/.
Recipe
myapp/
Cargo.toml
src/
lib.rs # domain logic
main.rs # thin CLI
bin/admin.rs # second binary
tests/
integration.rs
When to reach for this: Scaling codebase without circular dependencies.
Working Example
api-server/
crates/
domain/
infra/
api/
Cargo.toml # workspace
domainpure logic, no axumapiwires HTTP to domaininfradb, config
What this demonstrates:
- Dependency direction: api -> domain, infra -> domain
- Workspace members per crate
- Integration tests in
api/tests
Deep Dive
src/{module}.rs vs src/{module}/mod.rs. examples/ for usage demos. benches/ for Criterion.
Gotchas
- Circular module use - Compile error. Fix: Split module or extract shared.
- God lib.rs - Thousands of lines. Fix: Submodules.
- Tests only in unit - Miss public API. Fix:
tests/integration. - Binary logic duplication - Multiple mains copy code. Fix: Shared lib.
- Deep nesting - Long paths. Fix: prelude
pub use.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Flat modules | Small crate | Many domains |
| Workspace early | Clear boundaries | Hello world |
| Single bin | Tool | Library reuse |
FAQs
mod.rs vs name.rs?
Either works - prefer module_name/mod.rs for many files.tests/common?
tests/common/mod.rs helper.build.rs location?
Package root.config module?
config.rs or settings/.error module?
error.rs reexport.prelude.rs?
prelude module pattern.axum structure?
routes/ handlers/ state/.cli structure?
commands/ args in clap 4.migrate to workspace?
Extract lib crate first.architecture doc?
ADR for layout choices.Related
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+.