Vertical Slice Architecture

Organizes code by feature instead of by layer: each slice contains Web + App + Domain + Infra components for a specific functionality.

Context

In layered architectures, adding a feature requires touching 5 different folders. Cohesion is broken.

Solution

Each feature is organized in its own folder and contains EVERYTHING it needs: endpoint, validator, handler, query, events.

Features/
├── Orders.Place/
│   ├── PlaceOrderCommand.cs
│   ├── PlaceOrderHandler.cs
│   ├── PlaceOrderValidator.cs
│   └── PlaceOrderEndpoint.cs
└── Orders.Cancel/
    ├── CancelOrderCommand.cs
    ├── CancelOrderHandler.cs
    └── CancelOrderEndpoint.cs

#C# Example

// Features/Orders.Place/PlaceOrderEndpoint.cs
public class PlaceOrderEndpoint
{
    public static void Map(IEndpointRouteBuilder app) =>
        app.MapPost("/orders", async (PlaceOrderCommand cmd, IMediator m) =>
            Results.Ok(await m.Send(cmd)));
}

public record PlaceOrderCommand(Guid CustomerId, decimal Total) : IRequest<Guid>;

public class PlaceOrderValidator : AbstractValidator<PlaceOrderCommand>
{
    public PlaceOrderValidator() => RuleFor(x => x.Total).GreaterThan(0);
}

public class PlaceOrderHandler : IRequestHandler<PlaceOrderCommand, Guid>
{
    public Task<Guid> Handle(PlaceOrderCommand req, CancellationToken ct) => /* ... */;
}
When NOT to use it
  • When there are huge domain invariants that cross slices: you need an explicit domain (Clean / DDD).
Tradeoffs
Pro Con
High cohesion per feature Risk of duplicating code between slices
Fast onboarding Without discipline, features become entangled

#architecture #feature-folder