Carter in a CQRS API, advantages and alternatives.
In this project I wanted the API layer to stay small and structured. I like minimal APIs, but I don’t like having 200 endpoints inside Program.cs. That’s why I used Carter, it keeps the minimal API style and gives you a module system to organize endpoints by feature.
Repo used in this article:
https://github.com/stevsharp/ChainOfResponsibilityWithMediatR
Advantages of Carter
1) Feature-based organization without controllers
Carter pushes you to group endpoints in modules, for example PurchaseOrdersModule. This fits well with CQRS because you already think in features (Create, Approve, Reject, Get, List).
2) Minimal API feeling, but more maintainable
You still write endpoints in a minimal way (no heavy controller attributes), but you don’t end up with a giant Program.cs. Microsoft itself suggests structuring and organizing minimal APIs once they grow, Carter just gives a ready approach for it.
When you combine Carter + MediatR, the endpoint usually becomes:
- map route
- bind request
- call
Send
- return result
So your API layer stays thin and does not become “business logic + validation + database code”.
4) Testing and readability
Modules are easy to scan. If you want to see all Purchase Orders endpoints, you open one file. That’s a small thing, but in real teams it saves time.
5) Works nicely with Swagger and standard middleware
Carter is still based on ASP.NET Core endpoints, so you can keep standard middleware, and Swagger still works (with the normal setup).
Alternatives
Alternative 1, Controllers
Controllers (heavier):
Good when:
- you want strong conventions and attributes everywhere
- you already have a big MVC style codebase
- your team prefers the familiar controller structure
Less good when:
- you want very thin endpoints and feature modules
- you end up with “controller bloat” and many attributes
Alternative 2, Pure Minimal APIs (no Carter)
Minimal APIs are great, and they are official. If your API is small, this is the simplest approach.
Good when:
- small service with few endpoints
- you want the simplest possible setup
Less good when:
- endpoints grow and you need structure
Program.cs becomes huge
Microsoft has guidance on organizing minimal APIs because this is a real pain point once the API gets bigger.
Alternative 3, FastEndpoints (another popular option)
FastEndpoints is another library with a very feature oriented style, it also keeps endpoints separated and organized.
Good when:
- you want a strong endpoint-per-class structure
- you like conventions for validation, mapping, and request/response patterns
Less good when:
- you want the thinnest layer possible over native ASP.NET Core endpoints
Alternative 4, Minimal APIs with Endpoint Groups (manual modules)
You can also do your own “module system” without extra libraries:
- extension methods like
app.MapPurchaseOrderEndpoints()
- group routes with
MapGroup("/api/purchase-orders")
This is a valid approach and stays 100% framework-only.
Good when:
- you want no external dependency
- you like simple grouping patterns
Less good when:
- you still need to enforce structure across a team
- endpoint definitions become scattered if not disciplined
Why I still chose Carter here
For this project size, Carter gave me the best balance:
- minimal code style
- good organization
- no heavy framework feeling
And with CQRS + MediatR, it keeps the flow very clean: endpoint → mediator → handler.
References