
Posted by Mahdi

Vertical Slice Architecture vs Onion Architecture
Architecture debates often become unhelpfully absolute. Vertical slice architecture is not automatically modern, and onion architecture is not automatically over-engineered. They solve different problems. The useful question is not which diagram looks cleaner; it is which structure helps your team make changes safely, test important behaviour, and keep business rules understandable as the system grows.
This article compares vertical slice architecture and onion architecture for teams building or modernising business applications. It focuses on practical trade-offs: code organisation, dependency direction, testing, feature delivery, domain complexity, integration boundaries, and how to choose an approach without turning architecture into ceremony.
The Difference in One Screen
Both patterns care about maintainability, but they organise the application around different forces.
Vertical Slice
Groups code by feature or request. A slice can contain endpoint, validation, application logic, persistence, mapping, and tests for one use case.
Onion Architecture
Groups code by dependency rings. Domain model sits in the centre, while infrastructure, UI, database, and external tools sit outside.
Main Trade-off
Vertical slices optimise change locality. Onion architecture optimises domain isolation and dependency control.
Best Fit
Vertical slices suit feature-heavy systems where requests differ and delivery speed matters.
Best Fit
Onion architecture suits long-lived business systems with a rich domain model and complex behaviour.
Risk
Vertical slices can duplicate logic. Onion architecture can create too many abstractions if applied mechanically.
What Is Vertical Slice Architecture?
Vertical slice architecture organises software around features, requests, commands, queries, or business use cases instead of technical layers. Jimmy Bogard describes the style as grouping the concerns for a distinct request from front end to back end, then coupling along the axis of change. In that framing, a slice might include the route, request model, validation, handler, persistence query, response model, and tests for one operation.
The important idea is not folder naming. It is change locality. When a team adds a feature, they usually touch many technical concerns. A vertical slice keeps those changes close together so the team is less likely to modify shared services that unexpectedly affect unrelated features.
Vertical slices often pair naturally with CQRS-style thinking because reads and writes frequently have different needs. Martin Fowler describes CQRS as separating the model used to update information from the model used to read it, while warning that it can add risky complexity when applied where the benefit is not worth the cost. That caution matters: a vertical slice can be simple without becoming a full CQRS, event-sourced, multi-model system.
What Is Onion Architecture?
Onion architecture organises software around dependency direction. Jeffrey Palermo's original article describes a core domain model at the centre, with coupling directed inward. Infrastructure, UI, database access, file systems, external services, and tests sit toward the outside. The database is treated as external infrastructure, not the centre of the application.
This is valuable when the business domain is the hard part. If the domain model contains rules, invariants, policies, workflows, and language that must survive framework or database changes, onion architecture gives that model stronger protection. Interfaces, dependency inversion, repositories, services, adapters, and composition roots are used to keep infrastructure from leaking into the core.
Clean architecture, hexagonal architecture, ports and adapters, and onion architecture overlap heavily. Robert C. Martin's clean architecture article groups them around separation of concerns, independent business rules, and dependency rules that point inward. For teams comparing the terms, the practical theme is the same: protect important policy from volatile delivery mechanisms.
How to Choose the Architecture
Start from the kind of change your system sees most often.
Feature Change
If most work is adding or changing use cases, vertical slices usually reduce the number of shared files touched per feature.
Domain Complexity
If business rules and invariants are the hardest part, onion architecture can protect the domain model from infrastructure churn.
Team Maturity
Vertical slices require judgement about duplication and refactoring. Onion architecture requires discipline around abstractions and dependency direction.
Testing Strategy
Vertical slices often favour use-case integration tests. Onion architecture often favours unit tests around domain behaviour plus adapter tests.
Integration Boundaries
Systems with many external dependencies need clear ports, adapters, contracts, retry handling, and ownership regardless of folder structure.
Architecture Debt
If the codebase already has bloated service layers, either pattern can help, but migration should happen feature by feature.
Vertical Slice vs Onion Architecture: Practical Comparison
| Decision area | Vertical slice architecture | Onion architecture |
|---|---|---|
| Primary organisation | Feature, use case, request, command, query, or workflow. | Domain core, application layer, infrastructure, adapters, UI, and outer frameworks. |
| Dependency goal | Minimise coupling between slices and keep related feature code together. | Keep dependencies pointing inward so the domain does not depend on infrastructure. |
| Best for | Fast-moving product teams, CRUD-plus-workflow systems, APIs with many distinct endpoints, and systems where features change independently. | Long-lived business applications, complex domains, policy-heavy systems, and codebases where infrastructure must remain replaceable. |
| Testing style | Use-case or handler-level tests that exercise validation, persistence and behaviour for a slice. | Domain unit tests, application service tests, adapter tests, and integration tests at boundaries. |
| Common failure mode | Copy-paste logic across slices, inconsistent conventions, and missed refactoring when shared domain rules emerge. | Repository-for-everything, service-layer ceremony, mock-heavy tests, and abstractions that hide simple work. |
| Refactoring signal | When two or more slices repeat meaningful business rules, move that rule into a shared domain concept or policy. | When interfaces mirror only one implementation or services pass data through unchanged, remove or simplify the abstraction. |
The Hidden Similarity: Both Are About Boundaries
Vertical slice and onion architecture are often presented as opposites, but the best implementations share a boundary mindset. Vertical slice architecture draws boundaries around use cases. Onion architecture draws boundaries around the domain and infrastructure. Domain-driven design adds another useful lens: bounded contexts.
Microsoft's domain analysis guidance recommends designing around business capabilities rather than horizontal layers, and warns that service boundaries require careful thought because there is no mechanical process that produces the correct design. Its tactical DDD guidance also describes aggregates as consistency boundaries around entities and behaviour. These ideas support both architecture styles. Good boundaries follow business change, consistency needs, and operational ownership, not just diagrams.
When Vertical Slice Architecture Works Better
Vertical slice architecture is usually a strong choice when the application has many use cases that do not all need the same architecture. One query might need a fast projection. One command might need validation, persistence, and a domain event. Another workflow might call an external system. A single layered template can make all of those paths look artificially similar.
Use vertical slices when:
- features change independently and frequently;
- most work involves adding use cases rather than changing the core domain model;
- the existing service layer has become a large coordination point;
- read models and write models naturally differ;
- teams need clearer ownership of feature code;
- integration tests around use cases give more value than mock-heavy unit tests.
The main discipline is refactoring. Bogard explicitly warns that the approach assumes the team understands code smells and knows when to push complex logic into the domain. Without that discipline, vertical slices can become organised duplication.
When Onion Architecture Works Better
Onion architecture is usually a strong choice when the domain model is the asset. If the business logic is complex, long-lived, heavily tested, and expected to outlast frameworks or databases, protecting it is worth the structure. This is common in financial systems, logistics, insurance, health workflows, compliance-heavy products, pricing engines, and enterprise applications with deep business rules.
Use onion architecture when:
- domain invariants are more important than delivery speed alone;
- business rules must be testable without infrastructure;
- database, message broker, API, or UI choices may change over time;
- the team has enough experience to keep abstractions purposeful;
- the system needs clear ports and adapters around external services;
- multiple applications or interfaces share the same core behaviour.
The main discipline is resisting ceremony. If every feature requires several interfaces, services, repositories, mappers, and DTOs before any business value appears, the architecture is serving itself rather than the product.
You Can Combine Them
The most practical answer is often a hybrid. A system can use vertical slices at the application boundary while still protecting a domain model in the centre. For example, each feature slice can own its endpoint, request model, validator, handler, and response model, while shared domain entities, value objects, policies, and aggregates remain independent of infrastructure.
A useful hybrid structure might look like this:
- Features: CreateOrder, CancelOrder, SearchProducts, UpdateCustomerDetails, ExportInvoice.
- Domain: Order, Customer, Product, Money, PricingPolicy, OrderStatus, domain events.
- Infrastructure: database implementation, email provider, payment gateway, search index, message broker.
- Contracts: API models, integration events, external service clients, background job messages.
This avoids two extremes. The team does not need a giant application service layer for every feature, but it also does not bury important business rules inside handlers. Feature code can stay local until repeated behaviour proves it belongs in the domain.
A Migration Path for Existing Layered Applications
- Pick one feature: choose a low-risk use case with clear inputs, outputs, rules, and tests.
- Map the current path: identify controller, service, repository, mapper, validator, database calls, external calls, and tests.
- Create a slice: move use-case-specific request, validation, handler, response, and tests together.
- Protect shared rules: leave genuine domain behaviour in domain objects, policies, or services rather than copying it into the slice.
- Delete pass-through abstractions: remove interfaces and services that only forward calls without protecting a boundary.
- Repeat by change frequency: migrate the features that change most often before rewriting stable areas.
Do not perform an architecture migration as a big-bang folder shuffle. The value comes from making future changes easier, not from making the tree look fashionable.
Final Recommendation
Choose vertical slice architecture when feature change is the dominant pressure and the team can refactor duplicated logic into clearer domain concepts as it emerges. Choose onion architecture when the domain model is complex enough to justify stronger protection from infrastructure and delivery mechanisms.
For many business applications, combine the two: organise application use cases vertically, keep shared domain behaviour explicit, and keep infrastructure at the edge. The architecture should make important change safer and simpler. If it only adds folders and rules, it is not paying for itself.
Sources Checked
Vertical Slice and Onion Architecture FAQs
Short answers for teams comparing architecture options before a new build or modernisation project.
Modernise Architecture Without a Big-Bang Rewrite
VaniTech can help assess application boundaries, simplify service layers, protect domain logic, and plan architecture improvements around real delivery risks.