Back to Blog
#architecture#dotnet#microservices

.NET 8 Microservices Architecture Map

3 min read

A practical map of N-Layer, Clean Architecture, and Vertical Slice patterns inside a .NET 8 microservices system.

Why this architecture needs a map

A microservices solution can contain more than one architecture style. That is not automatically a problem. The real risk is when the team cannot explain which service owns which responsibility, where dependencies are allowed to point, and how data moves between services.

In this .NET 8 ecosystem, the architecture is intentionally mixed. Shopping.Web and Discount.Grpc fit a traditional N-Layer shape, Ordering follows Clean Architecture, and Catalog plus Basket use Vertical Slice Architecture.

The service patterns

Shopping.Web behaves like a layered web application. Razor Pages, View Components, models, and service classes are separated by technical concern, which is a reasonable fit for a UI-facing service that consumes downstream APIs.

Discount.Grpc is also layered, but its boundary is a gRPC contract. The important structure is the .proto definition, generated stubs, and service implementation that keep internal synchronous communication explicit.

Ordering is where the dependency rule matters most. Its Domain layer should not depend on infrastructure, web, EF Core, SQL Server, or messaging details.

Catalog and Basket are better understood as feature-oriented services. Each business feature can keep endpoint behavior, validation, command or query handling, and persistence close together.

Communication flow matters

Architecture is not only folder structure. In distributed systems, the network becomes part of the design.

  • YARP acts as the API Gateway and reverse proxy boundary.
  • Refit and HttpClientFactory support typed REST calls from the web layer.
  • gRPC handles internal synchronous communication where a typed contract is useful.
  • RabbitMQ and MassTransit support asynchronous integration between services.
  • Redis supports read-heavy Basket behavior through caching.

These choices create different failure modes. A slow gRPC call creates immediate caller pressure. A delayed message creates eventual consistency. A weak gateway policy can expose the wrong surface area.

Data ownership and persistence

The system uses more than one persistence model, which is normal for microservices. Catalog and Basket can use PostgreSQL and Marten where document storage and CQRS-style flows are practical. Ordering uses SQL Server and EF Core where relational consistency is more important. Discount can use SQLite because the data shape is small and bounded.

The important rule is not that every service uses the same database. The important rule is that each service owns the data it writes and exposes changes through contracts rather than shared tables.

Production risks to validate

Before calling this architecture production-ready, the team should validate more than happy-path requests:

  • Gateway request validation, authentication, authorization, and rate limiting.
  • Service-to-service timeout, retry, and failure behavior.
  • Message idempotency, dead-letter handling, and duplicate event processing.
  • Distributed tracing and correlation IDs across YARP, APIs, gRPC, and RabbitMQ.
  • Health checks and readiness checks for databases, Redis, and message brokers.

When this design is a good fit

This mixed architecture is a good fit when each service has a clear reason for its structure. A UI service does not need the same code organization as an ordering domain. A catalog feature does not always need the full ceremony of Clean Architecture.

The key is discipline. Use the simplest structure that protects the service's real change points, then validate the operational behavior before scaling the architecture further.