Preview: 0/2 free chapters read
Intermediate Level 7 min read
Production Project Structure
Organizing scalable Actix Web applications with clean domain layers.
As your backend grows, maintaining a single main.rs file becomes impossible. Following a domain-driven architectural structure keeps your codebase modular, testable, and maintainable.
#Recommended Domain Structure 1. **`handlers/`**: Responsible purely for extracting HTTP request data, validating parameters, calling service methods, and returning HTTP responses. 2. **`services/`**: Contains core business rules, calculation logic, and domain invariants independent of HTTP. 3. **`models/`**: Strongly-typed request/response Data Transfer Objects (DTOs) and database row mappings. 4. **`db/`**: Database connection pool setup, query builders, and migration scripts.
# Working Implementation
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
async fn get_users() -> impl Responder {
HttpResponse::Ok().json(serde_json::json!([
{ "id": 1, "username": "ferris" },
{ "id": 2, "username": "rustacean" }
]))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("API Gateway starting on http://0.0.0.0:8080");
HttpServer::new(|| {
App::new()
.service(
web::scope("/api/v1")
.route("/users", web::get().to(get_users))
)
})
.bind(("0.0.0.0", 8080))?
.run()
.await
} Key Architectural Takeaways
- •Separate business logic (services), database access (repositories), and HTTP interfaces (handlers).
- •Centralize application configuration in a strongly-typed Settings struct with config crate.
- •Organize routes into feature modules using web::scope.
Common Mistakes & Gotchas
- ×Placing database queries directly inside route handlers, mixing presentation and data layers.
Sponsored Infrastructure Partner
Deploy Lightweight 15MB Distroless Actix Containers
High-availability PostgreSQL connection pooling and NVMe storage.