How meysamhadeli/booking-modular-monolith works
1. System shape
- This repository is a modular monolith: one deployable solution, but split into bounded-context modules with clear ownership boundaries.
- The main business modules are Identity, Flight, Passenger, and Booking.
2. Top-level runtime entry points
- src/Api is the primary ASP.NET Core API host exposed to clients.
- src/Aspire/src/AppHost is a separate local orchestration host used to wire the services together during development and observability.
- deployments/docker-compose provides the containerized runtime, including infrastructure dependencies.
3. Request handling pattern
- The codebase follows Vertical Slice Architecture and CQRS.
- Requests are organized per feature, not per technical layer: each use case has its own command/query, handler, validator, and endpoint surface.
- API endpoints are intentionally thin and delegate to MediatR handlers.
4. Shared platform layer
- src/BuildingBlocks is the common foundation used across modules.
- It contains reusable infrastructure for:
- CQRS abstractions
- MediatR pipeline behaviors
- validation
- caching
- logging
- exception/problem-details handling
- OpenTelemetry instrumentation
- HTTP/JWT/OpenAPI helpers
- MongoDB, EF Core, MassTransit, Polly, and health check wiring
- This layer is the main architectural boundary that prevents modules from duplicating infrastructure code.
5. Flight module
- src/Modules/Flight is the largest business module and models the flight domain.
- It contains subdomains for Aircrafts, Airports, Flights, and Seats.
- Each subdomain has its own feature slices, DTOs, value objects, exceptions, and mappings.
- The module includes:
- an EF Core write model (FlightDbContext)
- a separate read model (FlightReadDbContext)
- migrations and seeders
- gRPC server implementation for internal access
6. Passenger module
- src/Modules/Passenger manages passenger records and exposes its own feature slices.
- It also uses a split between write-side persistence and read-side persistence.
- The module includes a gRPC server and an integration path from the Identity module via event/consumer flow.
- Its identity-related folder shows that passenger creation is partially driven by user-registration events.
7. Booking module
- src/Modules/Booking is the booking bounded context.
- It has a booking aggregate, projection/read model, and feature slice for creating bookings.
- Supporting files such as BookingProjection, BookingEventMapper, and BookingRoot indicate it uses a more event-centric model than the CRUD-style modules.
- The read model is separated from the domain/write model, consistent with CQRS and event-driven projection updates.
8. Identity module
- src/Modules/Identity owns authentication and authorization concerns.
- It combines ASP.NET Identity-style user/role data with IdentityServer/Duende-based auth infrastructure.
- It exposes a registration use case and persistence model for users, roles, claims, logins, and tokens.
- This module is the security boundary for the rest of the system.
9. Cross-module communication
- The solution uses two main integration styles between modules:
- gRPC for synchronous internal calls, especially where one module needs data from another.
- MassTransit for asynchronous event-driven integration.
- The Passenger module’s Identity/Consumers folder shows a concrete event consumer path from Identity/user registration into passenger creation.
- Shared contract files under BuildingBlocks/Contracts/EventBus.Messages define message boundaries between modules.
10. Persistence and data boundaries
- The architecture separates write side and read side storage in several modules.
- EF Core is used for relational persistence; the README says the write side is based on Postgres.
- MongoDB is used for read-side or denormalized views where appropriate.
- BuildingBlocks/EventStoreDB supports event-store-backed workflows and projections, especially relevant to booking-style event evolution.
11. Non-functional platform concerns
- Observability is a first-class subsystem:
- OpenTelemetry for tracing/metrics
- Prometheus and Grafana for metrics visualization
- Loki for logs
- Tempo/Jaeger-style tracing assets are included
- Health checks, retries, and problem-details middleware are part of the shared runtime behavior.
- The repo also includes Swagger/Scalar OpenAPI generation for API discovery.
12. Deployment and local development
- deployments/docker-compose stands up the application with its infrastructure dependencies.
- src/Aspire is used to orchestrate the app locally and provide a unified observability dashboard.
- Grafana dashboards and provisioning files under deployments/configs/grafana show the intended production-like monitoring setup.
13. Testing strategy
- Each module has its own test suite, commonly split into:
- unit tests
- integration tests
- for Flight, end-to-end tests
- The tests use xUnit, Testcontainers, and Respawn to exercise real infrastructure with isolated state.
- The test layout mirrors the production feature slices, which makes the tests part of the architecture rather than an afterthought.
14. How to draw the architecture
- A useful diagram would center on the API host and Aspire host, then show four bounded contexts behind it.
- Draw shared building blocks as a horizontal foundation layer consumed by all modules.
- Show synchronous gRPC links between modules where needed and asynchronous event bus links for cross-module reactions.
- Separate write models from read models inside each module, and call out the specialized infrastructure: EF/Postgres, Mongo, EventStoreDB, and observability stack.
Main entry points: Flight.csproj Flight module · Identity.csproj Identity module · Booking.csproj Booking module · Program.cs API host
Components 28
Runtime hosts
Entry points that host or orchestrate the modular monolith.
Shared platform
Cross-cutting building blocks reused by all modules.
- Building blocks · Common CQRS, validation, logging, telemetry, persistence, web, and integration helpers.
src/BuildingBlocks/BuildingBlocks.csproj - Event contracts · Cross-module integration message boundaries.
src/BuildingBlocks/Contracts/EventBus.Messages
Identity
Authentication and authorization bounded context.
- Identity module · Owns users, roles, tokens, registration, and auth infrastructure.
src/Modules/Identity/src/Identity.csproj - Register user · Registration use case surface for new users.
src/Modules/Identity/src/Identity/Features/RegisteringNewUser/V1/RegisterNewUser.cs - Users/roles · Identity persistence model for users, roles, claims, logins, and tokens.
src/Modules/Identity/src/Identity/Models/User.cs - Identity DB · Identity write-side database and migrations.
src/Modules/Identity/src/Data/IdentityContext.cs
Passenger
Passenger bounded context and its integration flow.
- Passenger module · Manages passenger records and registration completion.
src/Modules/Passenger/src/Passenger.csproj - User consumer · Consumes identity registration events to initiate passenger creation.
src/Modules/Passenger/src/Identity/Consumers/RegisteringNewUser/V1/RegisterNewUser.cs - Passenger write · Passenger aggregate and write-side persistence.
src/Modules/Passenger/src/Passengers/Models/Passenger.cs - Passenger read · Passenger read-side persistence for queries.
src/Modules/Passenger/src/Passengers/Models/PassengerReadModel.cs - Passenger gRPC · Synchronous internal access surface for passenger data.
src/Modules/Passenger/src/GrpcServer/Services/PassengerGrpcServices.cs
Flight
Flight bounded context with multiple subdomains and dual models.
- Flight module · Largest domain module covering aircrafts, airports, flights, and seats.
src/Modules/Flight/src/Flight.csproj - Flights · Flight lifecycle use cases and domain model.
src/Modules/Flight/src/Flights/Features/CreatingFlight/V1/CreateFlight.cs - Aircrafts · Aircraft management features and write/read models.
src/Modules/Flight/src/Aircrafts/Features/CreatingAircraft/V1/CreateAircraft.cs - Airports · Airport management features and write/read models.
src/Modules/Flight/src/Airports/Features/CreatingAirport/V1/CreateAirport.cs - Seats · Seat creation, availability, and reservation use cases.
src/Modules/Flight/src/Seats/Features/ReservingSeat/V1/ReserveSeat.cs - Flight write · Flight domain write database and transactional persistence.
src/Modules/Flight/src/Data/FlightDbContext.cs - Flight read · Flight read-side database and denormalized views.
src/Modules/Flight/src/Data/FlightReadDbContext.cs - Flight gRPC · Synchronous internal access surface for flight data.
src/Modules/Flight/src/GrpcServer/Services/FlightGrpcServices.cs
Booking
Booking bounded context centered on reservation creation and projections.
- Booking module · Reservation creation and event-centric booking model.
src/Modules/Booking/src/Booking.csproj - Create booking · Feature slice for creating reservations/bookings.
src/Modules/Booking/src/Booking/Features/CreatingBook/V1/CreateBooking.cs - Booking model · Booking aggregate, root, and projection mapping.
src/Modules/Booking/src/Booking/Models/Booking.cs - Booking read · Separated read model for booking queries.
src/Modules/Booking/src/Booking/Models/BookingReadModel.cs - Booking gRPC client · Calls flight and passenger services synchronously for booking workflows.
src/Modules/Booking/src/GrpcClient/Protos/flight.proto
Operations
Deployment, orchestration, and observability stack.
- Docker compose · Containerized application and infrastructure bootstrap.
deployments/docker-compose/docker-compose.yaml - Observability · Provisioned dashboards and telemetry backends for runtime visibility.
deployments/configs/grafana
Connections 33
- API host → Building blocks: uses · API host composes shared pipeline, web, telemetry, and persistence helpers.
- AppHost → Building blocks: uses · Aspire host relies on shared service defaults and observability wiring.
- API host → Identity module: hosts · API exposes identity endpoints and module services.
- API host → Passenger module: hosts · API exposes passenger endpoints and module services.
- API host → Flight module: hosts · API exposes flight endpoints and module services.
- API host → Booking module: hosts · API exposes booking endpoints and module services.
- Identity module → Register user: contains · Identity module centers on the registration slice.
- Identity module → Users/roles: owns · Identity owns user and role persistence.
- Identity module → Identity DB: persists to · Identity uses EF Core-backed relational storage.
- Identity module → User consumer: publishes events to · Identity registration emits integration events consumed by passenger.
- Passenger module → Passenger write: owns · Passenger maintains the write-side aggregate.
- Passenger module → Passenger read: projects to · Passenger keeps a separate read model.
- Passenger module → Passenger gRPC: serves · Passenger exposes internal synchronous access via gRPC.
- User consumer → Passenger write: creates · Registration consumer drives passenger creation flow.
- Flight module → Flights: contains · Flights is one of the core flight subdomains.
- Flight module → Aircrafts: contains · Aircrafts is one of the core flight subdomains.
- Flight module → Airports: contains · Airports is one of the core flight subdomains.
- Flight module → Seats: contains · Seats is one of the core flight subdomains.
- Flight module → Flight write: persists to · Flight write-side uses EF Core relational storage.
- Flight module → Flight read: projects to · Flight maintains a separate read-side store.
- Flight module → Flight gRPC: serves · Flight exposes internal synchronous access via gRPC.
- Booking module → Create booking: contains · Booking is centered on the create-reservation slice.
- Booking module → Booking model: owns · Booking uses an event-centric aggregate and projections.
- Booking module → Booking read: projects to · Booking separates query storage from the domain model.
- Booking module → Booking gRPC client: calls · Booking depends on flight and passenger data via gRPC.
- Booking gRPC client → Flight gRPC: sync calls · Booking queries flight capabilities synchronously.
- Booking gRPC client → Passenger gRPC: sync calls · Booking queries passenger capabilities synchronously.
- Booking module → Event contracts: consumes · Booking participates in shared integration contracts.
- Passenger module → Event contracts: consumes · Passenger consumes shared bus messages.
- Identity module → Event contracts: publishes · Identity emits user-registration integration messages.
- Flight module → Event contracts: publishes · Flight emits domain/integration messages for other modules.
- AppHost → Docker compose: complements · Aspire and compose provide local orchestration paths.
- Docker compose → Observability: provisions · Compose brings up telemetry and monitoring dependencies.