Architecture

CloudSeed is a modular monolith: one deployable application organized into vertical feature slices. Each slice keeps its routes, views, services, data access, and types together. Shared infrastructure lives in core.

CloudSeed modular monolith architecture showing requests flowing through Axum routing into feature slices, shared infrastructure, PostgreSQL, and external services

src/
├── auth/       Passwordless login, sessions, and rate limiting
├── core/       Configuration, database, email, errors, and shared views
├── health/     Process and database health endpoints
├── index/      Starter landing page
├── jobs/       Background jobs, retries, cron, and metrics
├── sentinels/  Example vertical feature slice
├── telemetry/  Structured logging and optional OTLP export
├── lib.rs      Router composition and shared application state
└── main.rs     Startup, workers, HTTP server, and shutdown coordination

migrations/     Application and job-queue database schema
docs/           Markdown documentation and source-controlled diagrams
tests/          Integration tests with disposable PostgreSQL databases
styles/         Tailwind CSS and DaisyUI source
static/         Runtime static assets
crates/         Internal workspace crates

Request flow

build_app composes feature routers and middleware around a shared AppState. Handlers receive only the state and request data they need. Database, email, background jobs, rate limiting, session signing, and the application base URL are wired at the application root.

Feature slices

Create a top-level module such as src/billing.rs, then keep implementation files under src/billing/. Start with only the files the feature needs:

  • *_routes.rs for HTTP handlers and route composition
  • *_views.rs for Maud HTML
  • *_service.rs for business operations
  • *_data.rs for database access
  • *_types.rs for feature-specific data types

Expose the slice's router from its top-level module and merge it in build_app.

Effects and testing

CloudSeed keeps external effects behind traits where substitution matters. EmailSender and JobQueue use production implementations in the running app and test implementations in focused tests. Integration tests exercise SQL and route wiring against real temporary PostgreSQL containers.