Modules & Crates Best Practices
How to Use This List
- Apply before splitting or merging crates in a workspace.
- Review public
lib.rsexports each release.
A - Module Layout
- Keep
main.rsthin; logic inlib.rs. Testable library core. - Group by domain (auth, billing), not layer only. Find files by feature.
- Limit
pub usereexports to curated prelude. Avoid export everything. - Prefer
crate::paths in library code over deepsuper::. Refactor-safe. - One module per file when file grows past ~300 lines. Split early.
B - Visibility
- Default private; escalate to
pubdeliberately. Smaller API surface. - Use
pub(crate)for internal cross-module API. Not world-visible. - Constructors validate invariants; private fields. Encapsulation.
- Document
#[non_exhaustive]on extensible public enums. Semver. - Hide implementation modules; expose traits/types only.
pub modsparingly.
C - Workspaces & Crates
- Centralize dependency versions in
[workspace.dependencies]. One lockfile truth. - CI runs
cargo test --workspace --all-features. Catch cfg gaps. - Publish only intended crates; virtual workspace root not published. crates.io policy.
- Enforce dependency direction (domain has no axum/sqlx). Hexagonal boundaries.
- Feature flags documented in README and
Cargo.tomlcomments.
D - Public API
- Semver and changelog for published crates. Breaking change discipline.
-
missing_docson public items. rustdoc completeness. - Examples in
examples/compile on CI.cargo test --examples. - MSRV in
rust-versionfield. Consumer expectations. - Avoid leaking
pubpaths to internal modules in docs. rustdoc#[doc(inline)]careful.
FAQs
When workspace?
Multiple publishable or logical crates.integration tests location?
tests/ at package root.prelude mandatory?
No - ergonomic for large libs.inline mod vs file?
File for non-trivial.circular deps?
Extract shared crate.build.rs?
Separate concern - link flags codegen.doc private?
cargo doc --document-private-items dev only.rename crate?
Major bump + deprecation.lint workspace?
workspace.lints table.next?
Unsafe Rust when needed.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+.