Why organize code by feature instead of by layer
Many .NET codebases still organize projects by layers (API, Application, Domain, Infrastructure). Although this works well, the approach can dilute feature cohesion, scattering business rules across multiple folders and making it harder to evolve the code safely.
Vertical Slice Architecture proposes organizing code by end-to-end features (request → handler → domain → persistence), reducing coupling between features, improving readability, and favoring incremental evolution. This article shows how to apply vertical slices in .NET pragmatically, without giving up your preferred patterns (DDD, CQRS, MediatR, Minimal APIs).
Vertical Slice Architecture concepts
- Vertical Slice: grouping all the artifacts needed for a specific feature into a single vertical “slice” (contracts, handler, validations, use cases, persistence).
- Feature focus: each slice owns its flow — from the HTTP entry point down to the domain and the related infrastructure.
- Independence: slices minimize dependencies on each other; changes to one feature rarely affect others.
- Compatibility: works with CQRS (Commands/Queries), MediatR (or without it), FluentValidation, EF Core (with a DbContext per module/slice, if it makes sense), Minimal APIs, or Controllers.
- Goal: local coherence > architectural “purity.” Optimize the developer's daily routine and clarity for maintenance.
Feature-based architecture with Vertical Slices
Instead of grouping by global layers, we organize by features. Example structure:
Key points of the approach
- Per-feature entry points: each slice publishes its own endpoints.
- Explicit use cases (Commands/Queries) per slice.
- Validations and mappings local to the feature.
- Inverted dependencies: slices depend on domain abstractions and ports; infrastructure implements them.
- Observability: metrics/logs/traces named by feature make troubleshooting easier.
Tip: you can start with a modular monolith and later evolve critical slices into microservices, if needed — the design already prepares the extraction.
Vertical Slices in .NET with Minimal APIs, MediatR and EF Core
Below is a minimal CRUD excerpt for Customers with Minimal APIs + MediatR + FluentValidation + EF Core (illustrative pattern; adapt it to your own utilities).
5.1. Endpoint (Create)
5.2. Contract and Validation
5.3. Handler (Use Case)
5.4. Bootstrap (Program.cs)
5.5. Query (GetById) — Another Slice of the Same Feature
Notice how each slice wraps its entire flow: DTO/Command/Query, validation (when there is input), handler, mappings, and endpoints.
Vertical Slices best practices and pitfalls
- Cut by feature, not by layer: keep what changes together cohesive.
- Name by use case:
CreateCustomer,ApproveOrder,ShipOrder. This improves traceability and logs. - Encapsulate validations close to the feature's entry point.
- Avoid generic “utility folders” that break the slice's cohesion.
- Lean, stable domain layer: entities/VOs and rules that outlive individual features.
- Per-slice observability: metrics and traces with names that reflect the use case (e.g.,
customers.create.duration). - EF Core: consider a modular DbContext (one per module/group of slices) to reduce migration conflicts.
- Cross-cutting without coupling: middlewares and behaviors (e.g., MediatR Pipeline Behaviors) for auditing, validation, and idempotency without polluting handlers.
When to use Vertical Slices and when to wait
Use Vertical Slices when
- the team wants to speed up delivery of features with autonomy and less collateral impact;
- the domain is large and changes frequently;
- you need localized testability (use-case tests without navigating global layers);
- you want to lay the groundwork for future extraction of modules or critical microservices.
Avoid (or postpone) when
- the system is very small and the complexity doesn't pay off;
- the team is still learning the domain; starting with a modular monolith may be simpler.
- there is no discipline around minimal standardization (naming, folders, endpoint/handler conventions), which can lead to “every slice done its own way.”
Vertical Slices: features as first-class units
Vertical Slices make features first-class units, reducing friction when evolving software. By grouping request, validation, use case, domain, and persistence by feature, you gain clarity, isolation, and predictability. Start by applying it to one area of the system and evaluate: the payoff is quick, especially in codebases with a high rate of change. In modern .NET scenarios, combining Minimal APIs + MediatR + FluentValidation + EF Core delivers a straightforward and robust experience.
Keep reading
- Clean Architecture in .NET: compares with the layered approach and shows when it still pays off.
- Minimal APIs in ASP.NET Core: pairs well with slices: lean endpoints that live next to their feature.
- Modular Monolith in .NET: shows how to take feature organization to modules with clear boundaries.
Want an architecture review of your .NET backend? See the backend and .NET architecture service.
