Vertical Slice Architecture is an architectural pattern where the application is organized by feature (business capability) instead of technical layers such as Controllers, Services, and Repositories.
Each feature contains everything it needs:
- API Endpoint
- Request
- Validation
- Business Logic
- Data Access
- Response
Instead of navigating across multiple folders, everything related to a feature stays together.
Traditional Layered Architecture
API
│
├── Controllers
│ EmployeeController.cs
│
├── Services
│ EmployeeService.cs
│
├── Repositories
│ EmployeeRepository.cs
│
├── DTOs
│
├── Models
│
└── Data
Vertical Slice Architecture
Application
│
├── Employees
│ ├── CreateEmployee
│ │ Command.cs
│ │ Validator.cs
│ │ Handler.cs
│ │ Endpoint.cs
│ │ Response.cs
│ │
│ ├── GetEmployee
│ │ Query.cs
│ │ Handler.cs
│ │ Endpoint.cs
│ │
│ └── DeleteEmployee
│
├── Departments
│
├── Attendance
│
└── Payroll
Advantages
✅ Feature-based organization
✅ Easier to navigate
✅ Better scalability for large applications
✅ Less coupling between features
✅ Smaller classes
✅ Simpler testing of individual handlers
✅ Fits naturally with CQRS
✅ Works well with Minimal APIs
✅ Reduces boilerplate (no unnecessary service/repository layers)
Disadvantages
❌ Can lead to duplicated helper code if common functionality isn’t extracted thoughtfully.
❌ Requires discipline to keep shared logic in appropriate cross-cutting components. ❌ New developers familiar only with layered architecture may need time to adjust. ❌ Large features can still become complex if not broken into smaller slices.
When to Use Vertical Slice Architecture
This architecture is a great fit for:
- Medium to large .NET applications
- Microservices
- REST APIs
- CQRS-based systems
- Clean Architecture implementations
- Modular monoliths
It may be unnecessary for very small CRUD applications with only a handful of endpoints.
Vertical Slice vs Layered Architecture
| Aspect | Layered Architecture | Vertical Slice Architecture |
|---|---|---|
| Organization | By technical layer | By feature |
| Navigation | Across multiple folders | Inside one feature folder |
| Business Logic | Service layer | Handler |
| Data Access | Repository | DbContext (typically) |
| API | Controllers | Minimal APIs or thin controllers |
| Testing | Services + controllers | Individual handlers |
| Scalability | Can become harder to navigate | Easier to scale by feature |
| CQRS Support | Optional | Excellent |
Why Vertical Slice Fits Microservices
| Traditional Layered | Vertical Slice |
|---|---|
| Shared services become large over time | Each use case is isolated |
| Changes span multiple layers | Most changes stay within one feature folder |
| High coupling between layers | High cohesion within each slice |
| Controllers become thin, services become “God classes” | Handlers remain focused on a single responsibility |
| Harder to onboard new developers | Easier to locate feature-related code |
| Repositories often add boilerplate | EF Core DbContext is commonly injected directly |
Best Practices for Vertical Slice in Microservices
- One microservice = one bounded context.
- One vertical slice = one business use case.
- Keep each handler focused on a single responsibility.
- Use CQRS to separate commands and queries.
- Use Entity Framework Core directly unless a repository abstraction is truly needed.
- Publish integration events (e.g., via Kafka or RabbitMQ) rather than making synchronous service-to-service calls where asynchronous communication is appropriate.
- Use the Outbox Pattern for reliable event publishing.
- Keep shared infrastructure (logging, authentication, caching, telemetry) outside feature folders.
- Keep domain rules in the domain model when they represent business invariants.
- Ensure each microservice owns its own database to maintain loose coupling.
Key Takeaway
In a microservices ecosystem:
- Microservice defines the business boundary (e.g., Student, Course, Payment).
- Vertical Slice defines a single business use case within that boundary (e.g., Create Student, Search Student, Refund Payment).
This combination provides strong modularity, aligns well with CQRS and event-driven design, and makes each service easier to develop, test, and evolve independently.
