Architecture Best Practices
Boundaries, cohesion, and API stability keep Rust codebases maintainable as teams and traffic grow.
How to Use This List
- Apply at greenfield kickoff and quarterly architecture reviews.
- Pair with Architecture Decision Checklist.
A - Boundaries
- Domain logic in dedicated crate(s). No axum/sqlx in domain.
- Dependency direction inward. infra -> domain <- api.
- Thin binaries.
mainwires config and server only. - DTOs at edges. Serde types != domain types when rules differ.
- Ports as traits. Swappable adapters for test/prod.
B - API and Errors
- Stable public crate API documented. Semver honored for libs.
- Typed errors per context. Map to HTTP/gRPC at edge.
- Validation at construction. Illegal domain states unrepresentable.
- Version breaking changes via ADR + migration. Changelog for consumers.
- Feature flags documented compile-time vs runtime.
C - Workspace and Build
-
[workspace.dependencies]pins. serde, tokio, axum aligned. - CI tests
--workspace. All members green. - MSRV policy enforced. rust-version in manifests.
- Extract crates when compile graph hurts. Not preemptive nano-crates.
- Forbidden dependency lint for domain (optional script).
D - Operations
- Config validated at boot. Fail fast on bad env.
- Observability baseline. tracing + metrics + health.
- Graceful shutdown. Drains in-flight work.
- Migrations separate from serve. Job or phase in deploy.
- Secrets never in repo/images.
E - Process
- ADRs for architecture forks. Link checklist decisions.
- Audit checklist quarterly. Track debt items.
- Refactor incrementally. Tests guard extractions.
- Problem/solution reference updated when patterns repeat.
- Onboarding reads ARCHITECTURE.md day one.
FAQs
minimum crates?
domain + api + infra for typical Axum/sqlx service.
monolith ok?
Until 2+ deployables or compile pain; then workspace.
shared kernel?
types crate ok; avoid dumping ground.
microservices?
Each service own workspace; share domain lib via crate publish.
frontend BFF?
api crate tailored to UI DTOs separate from public API crate optional.
data pipeline?
polars worker crate; API orchestrates jobs async.
security reviews?
auth crate boundary + supply chain audit.
doc diagrams?
C4 or simple dependency mermaid in ARCHITECTURE.md.
enforce boundaries?
CI script grep forbidden imports in domain.
legacy carve-out?
ADR with removal milestone; no unbounded exception.
Related
- Architecture Decision Checklist
- Workspace & Crate Boundaries
- Rust Architecture Decisions
- 50 Rust Rules
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+.