June 21, 2026
Vertical slice architecture in .NET: the most AI-agent-friendly way to structure a minimal API
What vertical slice architecture is, why it works better with AI agents than Clean Architecture, and how to structure a .NET 10 minimal API as vertical slices with contract tests.
Vertical slice architecture is the most AI-agent-friendly way to organize a .NET minimal API. That is the case not because it is new or clever, but because of a simple mechanical property: a change to one feature touches one folder. An agent that cannot wander is an agent that does not break things you did not ask it to touch.
What is vertical slice architecture (VSA) vs Clean Architecture / N-tier?
Vertical slice architecture organizes code around features (slices) rather than technical layers. Every file for a given feature - the endpoint, the handler, the request/response records, the validation, and the tests - lives in one folder. A change to the “Create Note” feature touches Features/Notes/, not the Domain layer, the Application layer, the Infrastructure layer, and the Presentation layer simultaneously.
Clean Architecture and N-tier organize code by technical concern. The same feature is split across multiple layers, each in its own project or folder. The code is highly organized by type of code, but highly scattered by feature. Adding a new field to a feature requires touching files in four or five different places.
N-tier (Controllers, Services, Repositories) is the classical layer stack. Clean Architecture is N-tier with a stricter dependency rule: inner layers cannot depend on outer ones, and the domain is framework-free. Both are legitimate. Neither is particularly agent-friendly.
| Property | N-tier / Clean Architecture | Vertical Slice Architecture |
|---|---|---|
| Code organization | By technical layer | By feature |
| Change to one feature | Touches multiple layers | Touches one folder |
| Cross-feature coupling | Low by design | Must be enforced explicitly |
| Onboarding to a new feature | Read four layers | Read one folder |
| AI agent blast radius | Wide | Narrow |
VSA is not a reaction against Clean Architecture. The two approaches solve different problems. The question is which one fits how you actually work - and how your agent works.
Why does VSA work better with AI agents?
With VSA, a change lives in one folder, so an agent doesn’t wander across Domain/Application/Infrastructure/Presentation while making a single feature change.
This matters because of how AI agents operate. When you ask an agent to “add a title field to the Create Note endpoint,” it needs to read the relevant files, understand the pattern, and apply the change. In a layered architecture, that change touches:
- The
Noteentity in the Domain project. - The
INoteRepositoryinterface in the Application project. - The
NoteRepositoryimplementation in the Infrastructure project. - The
CreateNoteCommandin the Application project. - The endpoint in the Presentation/API project.
- Possibly a DTO or mapping file.
Each of those reads loads more files into the agent’s context. Each edit is a chance for the agent to apply an inconsistent pattern or accidentally break something in a layer it was not supposed to touch. In Clean Architecture, the layers are the organizational principle. For an agent, they are friction.
In a vertical slice, that same change touches Features/Notes/CreateNote.cs and possibly the contract test. That is it. The agent reads one file, edits one file, and the test confirms the change. The principle here matches what the best architects say about coupling: maximize cohesion within a slice, minimize coupling between slices. An agent that stays within a slice cannot accidentally break another slice.
A second advantage is that the agent can use the existing slices as templates. When you ask it to add a new DeleteNote slice, it reads CreateNote.cs, understands the pattern, and replicates it. The pattern is local and visible, not distributed across layers.
How do you structure a .NET 10 minimal API as vertical slices?
Create a Features/ folder in your API project. Each slice gets its own subfolder. Within each slice, keep everything that belongs to that feature:
src/
Api/
Features/
Notes/
CreateNote.cs - endpoint + handler + request/response types
GetNotes.cs - endpoint + handler + response types
DeleteNote.cs - endpoint + handler
Program.cs
tests/
Api.Tests/
Features/
Notes/
CreateNoteTests.cs
GetNotesTests.cs
Each *.cs file in a feature folder contains the endpoint registration and the MediatR handler for that one operation. Keeping them together is what makes the slice “vertical” - you see the full HTTP contract and the implementation logic without switching files.
A concrete example from the github.com/Khavel/dotnet-claude-starter starter repo. The Notes feature is a slice:
// Features/Notes/CreateNote.cs
public record CreateNoteRequest(string Title, string Body);
public record CreateNoteResponse(Guid Id, string Title, string Body);
public class CreateNoteHandler : IRequestHandler<CreateNoteCommand, CreateNoteResponse>
{
// handler implementation
}
// Minimal API endpoint registration (called from Program.cs)
public static class CreateNoteEndpoint
{
public static IEndpointRouteBuilder MapCreateNote(this IEndpointRouteBuilder app)
{
app.MapPost("/notes", async (CreateNoteRequest req, ISender sender) =>
{
var response = await sender.Send(new CreateNoteCommand(req.Title, req.Body));
return Results.Created($"/notes/{response.Id}", response);
});
return app;
}
}
Everything the agent needs to understand the endpoint is in one file. When it writes a new slice, it has this file as the local template.
Thin endpoints
Endpoints stay thin: parse, validate, dispatch, return. They do not contain business logic. Business logic belongs in the handler. The endpoint’s job is to translate HTTP to a MediatR command and translate the result back to HTTP.
The interface boundary
If a slice needs infrastructure (a database, a file system, an external API), it reaches it through an interface defined in the slice or in a shared Common/ folder. The interface is the boundary between the slice and infrastructure. In the starter, notes are stored behind an INoteStore interface, which means the test can use an in-memory implementation and the production code can swap in a database-backed one without changing the handler.
Shared code
Cross-slice shared code (authentication, logging middleware, common response types) lives in Common/ or in a shared project. The rule is: nothing in Common/ is feature-specific. If a piece of code belongs to one feature, it stays in that feature’s folder.
How do contract tests fit a slice?
Contract tests in a VSA project are per-slice and exercise the endpoint from the outside. They verify the HTTP contract: given this request, the endpoint returns this status code and this response shape. They do not test the handler in isolation.
This is the right level of abstraction for an AI agent. When the agent adds or modifies a slice, it runs the contract test for that slice. If the test is green, the slice’s HTTP contract is intact. The agent does not need to understand the full call graph - it just needs the test to pass.
A contract test for the Create Note slice:
// Api.Tests/Features/Notes/CreateNoteTests.cs
public class CreateNoteTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public CreateNoteTests(WebApplicationFactory<Program> factory)
=> _client = factory.CreateClient();
[Fact]
public async Task Post_Notes_ReturnsCreated_WithNoteId()
{
var response = await _client.PostAsJsonAsync("/notes",
new { title = "Test Note", body = "Test body" });
response.StatusCode.Should().Be(HttpStatusCode.Created);
var note = await response.Content.ReadFromJsonAsync<CreateNoteResponse>();
note!.Id.Should().NotBeEmpty();
note.Title.Should().Be("Test Note");
}
}
This test is the safety net. If the agent changes the endpoint’s response shape in a way that breaks the contract, the test fails. The agent reads the failure, corrects the change, and reruns. That loop requires no human intervention.
When is VSA the wrong choice?
VSA works best when features are distinct. If your domain has extremely complex business logic shared across many features - a pricing engine used by dozens of slices, a risk calculation that every financial operation depends on - that shared logic becomes a cross-cutting concern that VSA does not organize well. You end up either duplicating logic across slices (wrong) or building a Common/ that becomes its own de-facto Domain layer (at which point you have Clean Architecture with extra steps).
VSA is an excellent fit for:
- API services where each endpoint maps to one user operation.
- CRUD-heavy systems where features are largely independent.
- Small-to-medium SaaS products where the team is small and speed matters.
- Projects where an AI agent is doing a significant portion of the implementation.
Clean Architecture or a rich domain model is a better fit for:
- Systems where the domain model is the product (complex financial, insurance, or healthcare logic).
- Teams that need to enforce strict dependency boundaries as a governance mechanism.
- Projects where the domain must be testable completely independently of infrastructure.
These are not mutually exclusive. You can use VSA for your API layer and a rich domain model for the complex business logic it invokes.
FAQ
What is vertical slice architecture? VSA organizes code around features (slices) rather than technical layers. Every file for a given feature lives in one folder. A change to a feature touches one folder, not four layers.
Why is VSA better for AI agents than Clean Architecture? With VSA, a change lives in one folder, so an AI agent doesn’t wander across Domain/Application/Infrastructure/Presentation while making a single feature change. The agent stays focused, and the blast radius of any mistake is narrow.
How do I structure a .NET 10 minimal API as vertical slices?
Create a Features/ folder in your API project. Each slice gets its own subfolder containing the endpoint, handler, and request/response types. The dotnet-claude-starter repo uses this structure.
When is VSA the wrong choice? VSA works best when features are distinct. If your domain has complex business logic shared across many features, a rich domain model or Clean Architecture may be a better fit.
Do contract tests work per slice? Yes. Each slice has its own contract test that exercises the endpoint from the outside (HTTP in, HTTP out). The test lives alongside the slice and is the safety net for agent-driven changes.
Building a production .NET SaaS, agent-first?
The github.com/Khavel/dotnet-claude-starter starter repo is a .NET 10 minimal API structured as vertical slices, with a contract test per slice and the agent operating layer (CLAUDE.md, MCP config, pre-approved commands) wired throughout. Sharpyard is the production kit built on the same foundation: auth, multi-tenancy, billing, and the full agent layer ready to go. Join the founding waitlist for early access and the founding price.
Related: Claude Code for .NET developers.
The full AI-native .NET SaaS starter kit.
Join the waitlist