Overview
When building modern .NET applications—especially APIs and microservices—developers often struggle with bloated layers, tight coupling, and features that are hard to change safely. Vertical Slice Architecture (VSA) is an architectural approach that addresses these issues by organizing code around features rather than technical layers.
Instead of grouping code by Controllers, Services, and Repositories, Vertical Slice Architecture groups everything needed for a single use case into one cohesive slice.
Traditional Layered Architecture (The Problem)
A typical layered architecture in .NET looks like this:
Controllers
Services
Repositories
Domain Models
While this approach is familiar, it often leads to:
- Tight coupling between layers
- Large, generic service classes
- Changes in one feature affecting unrelated features
- Difficult maintenance as the system grows
For example, adding a small feature may require touching multiple layers and files across the solution.
What Is Vertical Slice Architecture?
Vertical Slice Architecture organizes the system by feature or use case, not by technical concern.
Each slice represents a single business capability, such as:
- Create User
- Update Profile
- Get Order Details
Each slice contains everything it needs:
- Request / Command
- Handler / Business logic
- Validation
- Data access
- Response / DTO
All in one place.
Folder Structure Example
Instead of this:
Controllers/
Services/
Repositories/
You get this:
Features/
└── Users/
├── CreateUser/
│ ├── CreateUserCommand.cs
│ ├── CreateUserHandler.cs
│ ├── CreateUserValidator.cs
│ └── CreateUserResponse.cs
└── GetUser/
├── GetUserQuery.cs
├── GetUserHandler.cs
└── GetUserResponse.cs
Each folder is a vertical slice.

All files related to a single use case are organized within one folder, ensuring high cohesion. This structure simplifies development by making it easy to locate all relevant components for each feature since they are grouped together.
How It Works in .NET
Vertical Slice Architecture in .NET is flexible. You can absolutely combine a slice into a single file when the logic is simple.
Vertical Slice Architecture is commonly implemented using:
- Minimal APIs or Controllers (thin endpoints)
- MediatR (Command / Query handling)
- CQRS (optional but popular)
- FluentValidation
- Entity Framework Core (used inside slices)
Single-File Vertical Slice Example
This approach keeps the entire use case in one file. It works best for simple or moderately complex features.
public static class CreateUser
{
public record Command(string Email, string Name) : IRequest;
public class Validator : AbstractValidator
{
public Validator()
{
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress();
RuleFor(x => x.Name)
.NotEmpty()
.MaximumLength(100);
}
}
public class Handler : IRequestHandler
{
private readonly AppDbContext _db;
public Handler(AppDbContext db)
{
_db = db;
}
public async Task Handle(Command request, CancellationToken ct)
{
var user = new User(request.Email, request.Name);
_db.Users.Add(user);
await _db.SaveChangesAsync(ct);
return user.Id;
}
}
}
Endpoint mapping:
app.MapPost("/users", (CreateUser.Command cmd, IMediator mediator)
=> mediator.Send(cmd));
When to use single-file slices:
- CRUD-style operations
- Small to medium complexity
- Solo or small teams
- Rapid feature development
Multi-File Vertical Slice Example
As a feature grows, you may prefer to split the slice into multiple files while still keeping everything under the same feature folder.
Features/
└── Users/
└── CreateUser/
├── CreateUserCommand.cs
├── CreateUserValidator.cs
├── CreateUserHandler.cs
└── CreateUserEndpoint.cs
CreateUserCommand.cs
public record CreateUserCommand(string Email, string Name) : IRequest;
CreateUserValidator.cs
public class CreateUserValidator : AbstractValidator
{
public CreateUserValidator()
{
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress();
RuleFor(x => x.Name)
.NotEmpty()
.MaximumLength(100);
}
}
CreateUserHandler.cs
public class CreateUserHandler : IRequestHandler
{
private readonly AppDbContext _db;
public CreateUserHandler(AppDbContext db)
{
_db = db;
}
public async Task Handle(CreateUserCommand request, CancellationToken ct)
{
var user = new User(request.Email, request.Name);
_db.Users.Add(user);
await _db.SaveChangesAsync(ct);
return user.Id;
}
}
CreateUserEndpoint.cs (optional)
public static class CreateUserEndpoint
{
public static IEndpointRouteBuilder MapCreateUser(this IEndpointRouteBuilder app)
{
app.MapPost("/users", (CreateUserCommand cmd, IMediator mediator)
=> mediator.Send(cmd));
return app;
}
}
When to use multi-file slices:
- Complex business rules
- Larger teams
- Advanced validation or mapping
- Clear separation for testing
Vertical Slice Architecture encourages pragmatism over rules — start with one file, split only when needed.
No service layer required.
Key Principles
1. Feature-Centric Design
Each slice focuses on one use case and one reason to change.
2. High Cohesion, Low Coupling
Code that changes together lives together.
3. Independent Evolution
You can modify or refactor a slice without impacting others.
4. Thin Endpoints
Controllers or Minimal APIs only handle HTTP concerns.
Benefits of Vertical Slice Architecture
- ✅ Easier to understand and maintain
- ✅ Faster onboarding for new developers
- ✅ Reduced risk when changing features
- ✅ Scales well for large teams and microservices
- ✅ Encourages clean, testable code
When Should You Use It?
Vertical Slice Architecture is a great fit for:
- Medium to large .NET APIs
- Microservices
- Systems with rapidly changing business requirements
- Teams practicing Domain-Driven Design (DDD)
It may be overkill for very small or throwaway applications.
Clean Architecture vs Vertical Slice Architecture
Both Clean Architecture and Vertical Slice Architecture aim to build maintainable systems, but they organize code very differently.
High-level Difference
- Clean Architecture organizes code by technical layers
- Vertical Slice Architecture organizes code by business features
Folder Structure Comparison
Clean Architecture
Application/
Domain/
Infrastructure/
API/
Vertical Slice Architecture
Features/
└── Users/
├── CreateUser/
└── GetUser/
Side-by-Side Comparison
| Aspect | Clean Architecture | Vertical Slice Architecture |
|---|---|---|
| Organization | By technical layers | By features/use cases |
| Change impact | Often touches multiple layers | Usually isolated to one slice |
| Service layer | Central and reused | Often unnecessary |
| File navigation | Many files across folders | Few files in one place |
| Learning curve | Steeper | Easier for new developers |
| CQRS | Optional | Common but optional |
| Best for | Complex domains, long-term core systems | Fast-moving APIs, microservices |
Strengths of Clean Architecture
- Strong separation of concerns
- Clear dependency rules
- Excellent for very complex domains
- Works well with classic DDD
Strengths of Vertical Slice Architecture
- Feature-first, business-focused design
- Minimal coupling between use cases
- Faster development and refactoring
- Easier onboarding and maintenance
Important Note: You Can Combine Them
In real-world .NET systems, many teams combine Clean Architecture and Vertical Slice Architecture:
- Clean Architecture at a macro level (Domain, Infrastructure)
- Vertical Slices inside the Application layer
This hybrid approach gives you the best of both worlds: strong boundaries and feature-focused development.
Common Misconceptions
- ❌ “You must use CQRS” – Not required
- ❌ “No shared code allowed” – Shared code is fine if justified
- ❌ “No layers at all” – Infrastructure and cross-cutting concerns still exist
Conclusion
Vertical Slice Architecture shifts the focus from technical layers to business capabilities. In .NET, it pairs naturally with Minimal APIs, MediatR, and modern tooling to create systems that are easier to evolve, test, and scale.
If you find your application growing complex and difficult to change, Vertical Slice Architecture is well worth considering.