Menu
Theme

Vertical Slice Architecture

What Vertical Slice Architecture is, why it organises code by request instead of by layer, and how to keep slices from turning into copy-paste. For architects weighing it against Clean Architecture or combining the two.

Researched
15 Oct 2026
Reading time
6 min
Sources
15
Review due
15 Oct 2027
TL;DR
  • Organise by request, not by layer: each feature's endpoint, validation, logic and data access live together.
  • Core principle: minimise coupling between slices and maximise coupling within a slice (Jimmy Bogard).
  • Change stays local: a new feature adds code in one place instead of touching every layer.
  • It trades structure for skill: without layers to guide them, teams need refactoring discipline and mechanical guardrails.
  • Combines well with Clean: slices organise behaviour, a shared domain and the dependency rule protect the core.
On this page 9 sections
  1. The idea in one minute
  2. When it fits
  3. How a slice is built
  4. Worked example: a configuration tool
  5. Where it is used in practice
  6. Gains and costs
  7. How it goes wrong
  8. Guardrails and testing
  9. Origins

The idea in one minute

Vertical Slice Architecture organises code around individual requests: “validate a configuration”, “apply a configuration”, “register a device”. Everything one request needs sits together: its endpoint, request and response types, validation, handler and the data access only it uses. Jimmy Bogard summarises the principle as “minimize coupling between slices, and maximize coupling in a slice.”[1]

The argument is about where change happens. A new feature in a layered design touches a controller, a service, a repository and their interfaces, each in a different project. In a sliced design the same feature adds one folder. Bogard calls this coupling “along the axis of change”.[1]

A slice is a column, not a row. Layered designs group the same cells by row, so one feature change touches every row; a slice keeps a feature's cells together. Shared rules still live in a domain model underneath.

When it fits

Fits when… Doesn’t fit when…
Features are mostly independent requests (typical web APIs, admin and CRUD-heavy tools) Complex rules are shared by many features
Several developers add features in parallel and fight merge conflicts in shared layers You need compile-time boundaries; one project cannot stop a handler from doing anything
You already think in commands and queries (CQRS) A rich domain model is the heart of the system
The team is comfortable refactoring and spotting code smells The team is new and relies on layers as guidance

These criteria follow Jovanović’s 2026 assessment,[9] and Bogard’s own precondition: the approach assumes the team understands code smells and refactoring.[1]

How a slice is built

  • One folder (or one file) per request. Bogard’s reference app keeps the query, validator, command, mapping and handlers of one page in a single file.[5]
  • Each slice chooses its own approach. Start with a simple transaction script; refactor to domain objects when smells appear. New features only add code, they do not change shared code.[1]
  • Commands and queries fall out naturally, which is how CQRS arrived “out of the gate” in Bogard’s own move away from onion architecture.[1]
  • A mediator is optional. MediatR is common in .NET samples, but became commercial in 2025 for companies above a revenue threshold;[6] plain handlers or endpoint libraries (REPR: request, endpoint, response) work just as well.[12]

Where shared logic goes

Jovanović separates three kinds of sharing:[8]

Kind Where it goes
Technical infrastructure (logging, results, pipelines) Shared freely
Domain rules (invariants, calculations) Pushed into entities and value objects
Logic shared by a few related slices A local Shared folder inside that feature area

His heuristics: one duplicate is fine, three should raise an eyebrow, and duplication is cheaper than the wrong abstraction.[8]

Worked example: a configuration tool

An illustrative layout. Slices own requests; the domain model holds rules many slices need.

src/ConfigTool.Api/
  Features/
    Configurations/
      ValidateConfiguration/
        Request.cs     // record: DeviceId, Payload
        Validator.cs   // shape and schema checks
        Handler.cs     // loads the device profile, asks the domain
        Endpoint.cs    // POST /devices/{id}/config:validate
      ApplyConfiguration/ ...
      Shared/          // only for configuration slices
    Devices/
      RegisterDevice/ ...
  Domain/              // DeviceProfile, ConfigRule: shared invariants
  Infrastructure/      // DbContext, device protocol adapters
tests/
  ConfigTool.IntegrationTests/Features/Configurations/
  ConfigTool.ArchitectureTests/
public static class ValidateConfiguration
{
    public sealed record Request(DeviceId DeviceId, ConfigPayload Payload);

    public sealed class Handler(ConfigDb db)
    {
        public async Task<ValidationReport> Handle(Request req, CancellationToken ct)
        {
            var profile = await db.DeviceProfiles.SingleAsync(p => p.Id == req.DeviceId, ct);
            return profile.Validate(req.Payload);   // the rule lives on the domain object
        }
    }
}

Where it is used in practice

  • Bogard’s reference application (Contoso University) and his talks since NDC Oslo 2015.[2][5]
  • Ardalis’ Clean Architecture template ships a minimal, single-project variant organised as vertical slices next to the classic four-project layout.[12]
  • SSW publishes it as a consulting rule (“features do not reference each other”)[13] and ships a .NET template with architecture tests built in.[14]
  • Combined with Clean Architecture: slices organise behaviour while Clean Architecture controls dependency direction.[10] Bogard’s own session covers mixing slices with layers, CQRS and DDD.[3]

Gains and costs

What it buys

  • Local change. A feature is one folder; deleting a feature is deleting a folder.
  • Fewer merge conflicts. Parallel features stop meeting in shared service and repository classes.
  • Right-sized code per feature. Simple requests stay simple; complex ones get domain objects.
  • Natural CQRS. Commands and queries are separate slices from day one.
  • Fits AI-assisted work. A slice fits in one context window and limits the blast radius of a change.

What it costs

  • Needs skill. Without layers as guidance, quality depends on refactoring discipline.
  • Duplication risk. Similar slices drift into copy-paste unless rules move into the domain.
  • Weaker compile-time boundaries. In one project, nothing stops a handler from reaching anywhere.
  • Shared rules need a home. Rule-heavy systems still need a protected core.

How it goes wrong

  1. The Common junk drawer. A shared Common or Utils project collects everything and brings back the coupling slices were meant to remove.[8]
  2. Slices calling slices. Use the domain, events or a small public facade instead of reaching into another slice’s handler.[8]
  3. Anaemic slices. Every rule written inline in handlers, copied three times, never pushed into the domain.
  4. Shared DTOs. One request type reused across slices couples them through the back door.
  5. Abstracting too early. Generic base handlers and repositories before the third duplicate.
  6. Huge slices. A use case that grows until it does too much; split it like any other oversized class.[9]

Guardrails and testing

Bogard’s 2026 talk is explicit that slices remove some structural guardrails and that mechanical ones must replace team discipline: architecture tests, conventions kept in the repository, and a reference slice to copy.[4]

  • Architecture tests (for example NetArchTest) enforce that features do not reference each other and that the domain does not depend on infrastructure.[15]
  • Conventions in the repo: a short guide and one exemplary slice new features copy.
  • Test by feature, not by layer: name tests after slices, drive them through the real HTTP boundary against a real database in a container, and unit-test only validators and complex domain logic.[11] Bogard’s reference app uses integration tests only, with a fixture that sends requests through the same pipeline as production.[5]

Origins

  • 2015: Bogard’s talk “SOLID Architecture: Slices not Layers” at NDC Oslo, after moving away from onion architecture toward CQRS.[2]
  • 2018: the blog post “Vertical Slice Architecture” that gave the style its name and principle.[1]
  • 2021 onward: practitioners such as Derek Comartin frame it as a question of coupling and dependencies: things that change together belong together.[7]
  • 2026: Bogard positions slices as guardrails for AI-assisted development, paired with architecture tests and repository conventions.[4]

Key takeaways

  1. Slices couple along the axis of change: things that change together live together.
  2. Start each slice simple (a transaction script) and push logic into the domain when it repeats; duplication is cheaper than the wrong abstraction.
  3. Avoid a Common junk drawer and slices calling slices; share through the domain or events instead.
  4. Replace the guardrails layers gave you with architecture tests, conventions in the repo and a reference slice.
  5. Test by feature, through the real boundary, not layer by layer with mocks.

Sources

  1. Vertical Slice Architecture · Jimmy Bogard, 2018Primaryjimmybogard.com
  2. SOLID Architecture: Slices not Layers (NDC Oslo 2015) · Talk recording recordPrimaryav.tib.eu
  3. Vertical Slice Architecture (session abstract) · Jimmy BogardPrimarysessionize.com
  4. Vertical Slice Architecture: Effective Guardrails for AI Development · Jimmy Bogard, 2026Primarysessionize.com
  5. ContosoUniversityDotNetCore-Pages · Bogard's reference applicationReferencegithub.com
  6. AutoMapper and MediatR going commercial · Jimmy Bogard, 2025Primaryjimmybogard.com
  7. Restructuring to a Vertical Slice Architecture · Derek Comartin, 2021Secondarycodeopinion.com
  8. Vertical Slice Architecture: where does the shared logic live? · Milan Jovanović, 2025Secondarymilanjovanovic.tech
  9. When to choose Vertical Slice Architecture · Milan Jovanović, 2026Secondarymilanjovanovic.tech
  10. Vertical Slice Architecture in .NET: complete guide · Milan Jovanović, 2026Secondarymilanjovanovic.tech
  11. Testing vertical slices in .NET · Milan Jovanović, 2026Secondarymilanjovanovic.tech
  12. Minimal Clean Architecture (min-clean) · Steve Smith (Ardalis) templateReferenceardalis.github.io
  13. SSW Rules: Vertical Slice Architecture · Consultancy guidanceSecondaryssw.com.au
  14. SSW.VerticalSliceArchitecture.Template · .NET template with architecture testsReferencenuget.org
  15. NetArchTestReferencegithub.com
↑ ↓ to moveEnter to openFull-text search by Pagefind