# booking-modular-monolith is a working .NET 10 reference, not a library

> meysamhadeli/booking-modular-monolith is a reference implementation of a modular monolith on .NET 10 that stacks Vertical Slice Architecture, DDD, CQRS with MediatR, event driven messaging on RabbitMQ through Wolverine, an event store, gRPC between modules and Aspire for local orchestration. It is a template to read and copy from, with a sister microservices version and a shared infrastructure library, not a dependency to install.

**meysamhadeli/booking-modular-monolith** — A practical Modular Monolith architecture with the latest technologies and architecture like Vertical Slice Architecture, Event Driven Architecture, CQRS, DDD, gRpc, Wolverine, and Aspire in .Net 10.

- Repository: https://github.com/meysamhadeli/booking-modular-monolith
- Stars: 545 · Forks: 100
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/meysamhadeli-booking-modular-monolith

## A reference implementation you read, not a package you install

booking-modular-monolith is presented as a practical Modular Monolith architecture with the latest technologies and architecture like Vertical Slice Architecture, Event Driven Architecture, CQRS, DDD, gRpc, Wolverine and Aspire in .Net 10. The wording matters, because this is a sample application, not a library. There is no package to add to your solution, no API to call. The value is that the whole thing is laid out in source, with a real booking domain in it, so you can see how the patterns fit together rather than reading them one at a time. The repository topics make the intent obvious, with modular-monolith, vertical-slice-architecture, cqrs, ddd, event-driven-architecture, event-sourcing, messaging, wolverine, aspire, kubernetes, docker, opentelemetry, oauth2 and boilerplate all listed. The author also publishes two sibling projects, a booking with microservices architecture and a booking with monolith architecture, which is a good way to read the same domain at three levels of decomposition, and a reusable infrastructure library called Griffin that holds the shared plumbing. The licence is MIT, the primary language is C#, and the last push was on 2026-10-08.

## Vertical slices with DDD and CQRS inside each module

The architecture goals in the README are a list, and one of them sets the tone. It says it uses Vertical Slice Architecture at the architecture level, which means the unit of organisation is a feature, not a layer, so a use case and the handler, validation and endpoint that belong to it live together instead of being split across controller, service and repository folders. Business logic is implemented with Domain Driven Design, and CQRS is implemented with the MediatR library, with FluentValidation and a validation pipeline behaviour on top of MediatR so that invalid commands are rejected before a handler runs. Endpoints are all Minimal API. The persistence story is deliberately split. Postgres is the write side database and MongoDB is the read side database, and the Booking module additionally uses an Event Store for the write side to store all historical change of the aggregate. That combination is the most opinionated decision in the project, and it is the one to argue with first, because a read model fed by events has to be rebuilt when it drifts, and the README's own Challenges section is where that kind of argument belongs.

## Wolverine carries the inbox and outbox guarantees

The messaging layer is where the design gets specific. The project uses RabbitMQ on top of Wolverine for Event Driven Architecture, and Wolverine is described as a durable messaging and local workflow library for .NET with RabbitMQ transport, inbox and outbox support and local queues. Two guarantees are called out separately, and they are the parts worth reading twice. The durable Inbox Pattern is used for ensuring message idempotency for the receiver and exactly once delivery, and the durable Outbox Pattern is used for ensuring no message is lost, with at least one delivery. Put together, that is the standard transactional messaging story, where a state change and the message announcing it are committed together, and the consumer deduplicates on the way in. The pieces that make it work are named in the technology list, including MVC Versioning API for service API versioning, Scrutor for assembly scanning and decoration of dependency injection registrations, Polly for resilience and transient fault handling with retry, circuit breaker, timeout, bulkhead isolation and fallback, EasyCaching for caching, and Mapster as the convention-based object to object mapper. gRPC is used for internal communication between modules, which keeps module-to-module calls off the public HTTP surface.

## Aspire runs the whole thing locally

Aspire is used for service discovery, observability and local orchestration of microservices, and that last word is the interesting one in a monolith, because the modules still talk to each other over gRPC and RabbitMQ and still need somewhere to run those dependencies. The repository backs this up with an .aspire/ directory, a global.json that pins the SDK, a deployments/ directory for the Docker Compose and Kubernetes deployment mechanism, and a booking.rest file, which is a REST client collection you can open in a tool like Visual Studio to call the running endpoints without hand-writing requests. There is an Open in GitHub Codespaces badge, so a working environment is one click away, and the README's table of contents lists separate sections for configuration certificate, Aspire, Docker Compose, build, run and test, which tells you the local setup is treated as a first-class part of the project rather than an afterthought. Docker Compose and Kubernetes are both listed as the deployment mechanism, so the same topology is expressed for a laptop and for a cluster.

## Observability, health checks and identity are all in the box

The supporting stack in this reference is unusually complete, and it is listed explicitly rather than implied. Logging uses Serilog with Kibana on top. Distributed tracing uses OpenTelemetry on top of Jaeger, and monitoring uses OpenTelemetry on top of Prometheus and Grafana. Health checks report the health of application infrastructure components. Authentication and authorization are based on OpenID Connect and OAuth 2 through DuendeSoftware IdentityServer, described as the most flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core. API documentation is handled by AspNetCore OpenApi for built-in OpenAPI document generation, with Scalar and Swagger UI for rendering API references, and MVC Versioning API for service API versioning. Test tooling is worth singling out. Unit tests use Nsubstitute for mocking dependencies, and end-to-end and integration tests use testcontainers, which means the tests run against real containers rather than fakes. That is a heavier and slower test suite, and it is also the only version of these tests that tells you whether the messaging and database boundaries actually work.

## The toolchain is wired through package.json and dotnet tools

The build tooling is a small but telling part of the repository. package.json exists mainly to drive dotnet tooling and git hooks, and its scripts show the workflow:

```json
  "scripts": {
    "prepare": "husky && dotnet tool restore",
    "format": "dotnet tool run dotnet-csharpier booking-modular-monolith.sln",
    "ci-format": "dotnet tool run dotnet-csharpier booking-modular-monolith.sln --check",
    "upgrade-packages": "dotnet outdated --upgrade"
  },
```

The prepare script runs husky and restores the dotnet tools, which is why a .config/ directory sits in the tree, since that is where the local tool manifest lives, and the .husky/ directory holds the git hooks. The dev dependencies are husky 9 and the commitlint CLI with the conventional config, and commitlint.config.js at the root means commit messages are checked against a conventional format, so the history is machine readable. Formatting is handled by dotnet-csharpier across the solution, with a separate ci-format script that only checks, which is what a pipeline would run. The upgrade-packages script wraps dotnet outdated with the upgrade flag, which is the routine maintenance path for a project that pins a large number of NuGet packages. Directory.Build.props and Directory.Build.targets at the root carry build settings that apply to every project in the solution, which is how a template keeps those settings consistent as projects are added.

## Where this is the wrong starting point

The honest limitation is weight. The local environment implied by the project includes Postgres, MongoDB, RabbitMQ, an event store, an Aspire orchestrator, Prometheus, Grafana, Jaeger, Kibana and an identity provider, and the test suite adds testcontainers on top. A team with one small service and three developers cannot carry that. The second limitation is the dual write and read database. Keeping Postgres as the write side and MongoDB as the read side buys fast reads, but it also means the read model is a projection that has to be kept in step, and the event store for the Booking module adds a third representation of the same aggregate. That is a deliberate trade and it is the right one at a certain scale, but it is a trade, and the README lists a sibling plain monolith project for the cases where it is not. The third limitation is that a reference implementation is not a framework. Everything here is hand written in this repository, so copying a pattern means copying code, and the shared infrastructure lives in a separate repository, Griffin, which you would either take wholesale or not at all. The alternative to the modular monolith here is the author's own microservices version, and the difference in approach is the point of the exercise: the same domain, the same patterns and the same message contracts, but deployed as separate services with network boundaries, independent deployment and the operational cost that comes with them.

## Conclusion

booking-modular-monolith suits developers who want to see a modular monolith assembled from current .NET tooling rather than described in a diagram, and who are willing to read a large reference codebase. It does not suit a small product that cannot carry Postgres, MongoDB, RabbitMQ and a full observability stack in development, since that is what the local setup implies. Before copying it, check the module boundary in src/ and decide whether the write side and read side split fits your data, and note the last push was on 2026-10-08 with v1.1.0 released on 2026-10-07.

## FAQ

### What is booking-modular-monolith and what is it for?

It is a reference implementation of a modular monolith on .NET 10 that uses Vertical Slice Architecture, DDD for business logic, CQRS with MediatR, event driven messaging on RabbitMQ through Wolverine, gRPC for internal communication and Aspire for local orchestration. The author also publishes microservices and plain monolith versions of the same booking domain.

### How does the booking-modular-monolith project handle messaging reliability?

It uses Wolverine's durable Inbox Pattern to ensure message idempotency for receivers and exactly once delivery, and its durable Outbox Pattern to ensure no message is lost, with at least one delivery. RabbitMQ is the transport on top of Wolverine.

### Which databases does the booking-modular-monolith reference use?

Postgres is the write side database and MongoDB is the read side database. The Booking module additionally uses an Event Store on the write side to store all historical change of the aggregate.

### How are code formatting and dependencies maintained in booking-modular-monolith?

The npm scripts wrap dotnet tooling: prepare runs husky and dotnet tool restore, format and ci-format run dotnet-csharpier over the solution, and upgrade-packages runs dotnet outdated with the upgrade flag. Commit messages are checked by commitlint with the conventional config.

## Sources

- [Issues](https://github.com/meysamhadeli/booking-modular-monolith/issues)
- [License: MIT](https://github.com/meysamhadeli/booking-modular-monolith/blob/main/LICENSE)
- [meysamhadeli/booking-modular-monolith on GitHub](https://github.com/meysamhadeli/booking-modular-monolith)
- [README](https://github.com/meysamhadeli/booking-modular-monolith/blob/main/README.md)
- [Releases](https://github.com/meysamhadeli/booking-modular-monolith/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/meysamhadeli-booking-modular-monolith
