Hexagonal Architecture — Rust
Rust-Specific Rules
Section titled “Rust-Specific Rules”Allowed dependencies in core
Section titled “Allowed dependencies in core”serde— serialization traits and derive macros only (format-agnostic)thiserror— typed error definitionsasync-trait— async port definitionsuuid,chrono— value objectshttp— HTTP types as pure value objects (StatusCode,Uri,HeaderMap…) — not as a client
Forbidden in core
Section titled “Forbidden in core”serde_json,serde_bson,quick-xml— format-specific serialization (belongs in infra)mongodb,sqlx,diesel— database driversaxum,actix,rocket— web frameworksreqwest,hyper— HTTP clientsjsonwebtoken,openidconnect— auth implementationsanyhow— not allowed in port (trait) signatures
Port Definition Pattern
Section titled “Port Definition Pattern”// core — defines the contract#[async_trait]pub trait UserRepository: Send + Sync { async fn find_by_id(&self, id: UserId) -> Result<Option<User>, UserError>;}Adapter Implementation Pattern
Section titled “Adapter Implementation Pattern”// infrastructure — implements the contractpub struct MongoUserRepository { /* ... */ }
impl UserRepository for MongoUserRepository { async fn find_by_id(&self, id: UserId) -> Result<Option<User>, UserError> { // MongoDB-specific code here }}No Leaky Abstractions
Section titled “No Leaky Abstractions”// BAD — infra type in domainpub struct User { pub id: mongodb::bson::oid::ObjectId,}
// GOOD — pure domain typepub struct UserId(pub Uuid);pub struct User { pub id: UserId,}Cargo.toml Checklist
Section titled “Cargo.toml Checklist”- Core crate has no infra dependencies
- No
use mongodb::/use axum::/use sqlx::/use reqwest::in core - Port signatures use typed errors (
thiserror), notanyhoworBox<dyn Error>