Skip to main content

Command Palette

Search for a command to run...

Minimal APIs vs Controllers in ASP.NET Core: Which to Choose

Updated
9 min read

Choosing between Minimal APIs and Controllers is one of the first real decisions you face when starting a new ASP.NET Core project in .NET 10 - and it is a decision that is harder to reverse than it looks on day one. In production I have set up both, and the right choice depends less on personal taste and more on team size, project lifecycle, and how much abstraction your endpoints actually need. The complete patterns we cover here - including the decision framework we use at Coding Droplets - go deeper on Patreon, with annotated, production-ready source code that maps directly to what enterprise teams actually ship.

If you want to see this decision playing out inside a real codebase from setup all the way to a deployed API, Chapter 1 of the Zero to Production course walks through the Controllers vs Minimal APIs trade-off head-to-head in a working .NET 10 project - so you can see the practical difference, not just the theory.

ASP.NET Core Web API: Zero to Production

Both approaches are fully supported in .NET 10 and neither is going away. But they optimise for different things. This comparison covers the real trade-offs: routing, middleware integration, testability, team ergonomics, and performance - so you can make the call with confidence.

What Are Minimal APIs?

Minimal APIs were introduced in .NET 6 as a way to write web endpoints with less ceremony. Instead of a class inheriting from ControllerBase, you map routes directly in Program.cs or a thin extension method:

app.MapGet("/products/{id}", async (int id, IProductService svc) =>
    await svc.GetByIdAsync(id) is { } product
        ? Results.Ok(product)
        : Results.NotFound());

The appeal is obvious: no boilerplate, fast to set up, and great for small APIs or microservices where the overhead of a full controller feels wasteful. In .NET 10, Minimal APIs have matured significantly - route groups, endpoint filters, typed results, and OpenAPI support are all first-class now.

What Are Controllers?

Controller-based APIs have been the default ASP.NET Core model since the beginning. A controller is a class decorated with [ApiController] that groups related endpoints together:

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _svc;
    public ProductsController(IProductService svc) => _svc = svc;

    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id) { ... }
}

Controllers benefit from years of tooling, convention, and ecosystem support. Action filters, model binding, built-in validation integration with [ApiController], and broad community knowledge all weigh in their favour.

Side-by-Side Comparison

Aspect Minimal APIs Controllers
Boilerplate Very low Moderate
Routing MapGet/MapPost/MapGroup Attribute + convention routing
Middleware / Filters Endpoint filters Action filters + middleware
Model binding Parameter injection + [FromBody] Model binding + [ApiController] auto-validation
Auto 400 on validation fail Manual Automatic with [ApiController]
OpenAPI / Swagger support .NET 9+ native (good) Long-standing, mature
Testability Slightly more complex to mock Well-established patterns
Organisation at scale Harder without discipline Natural grouping by controller
Performance (raw throughput) Marginally faster Marginally slower

The performance difference is real but tiny - we are talking single-digit milliseconds on the cold path in benchmarks published by the ASP.NET Core team. Do not choose either based on benchmark micro-optimisation alone.

When Should You Use Minimal APIs?

Minimal APIs win when:

  • The API is small and focused - a microservice with 5-10 endpoints has no need for the structure controllers impose
  • You are building an internal service or background API - low surface area, small team, fast iteration matters more than layered structure
  • Performance is the primary concern - embedded edge functions, ultra-low-latency read endpoints, or high-throughput stream processors where every allocation counts
  • The team is small and experienced - Minimal APIs require you to enforce your own organisation discipline; experienced teams do this well, larger or mixed-experience teams often drift
  • You want to co-locate route definitions with a module - the extension method pattern (app.MapProductEndpoints()) keeps routes and their logic in one file per feature

In production I have seen Minimal APIs work beautifully in teams of 2-3 engineers building bounded, stable services. The trade-off that bit us was when those services grew - adding cross-cutting concerns (audit logging, correlation IDs, permission checks) to endpoint filters across 40+ routes is more painful than doing the same with a base controller.

When Should You Use Controllers?

Controllers win when:

  • The team is larger or mixed-experience - convention over configuration is a feature when onboarding developers who are unfamiliar with the codebase
  • You need sophisticated action filters - controllers have a richer filter pipeline (action, result, exception filters) built in; endpoint filters in Minimal APIs cover the basics but not the full model
  • Auto model validation matters - [ApiController] gives you automatic 400 responses on validation failure for free; in Minimal APIs you wire this manually
  • The API will grow in surface area - as endpoint count grows, the organisational clarity of controllers starts to pay compound dividends
  • You are working in a monolith - large APIs with dozens of resource types, admin surfaces, and versioning requirements benefit from the controller-per-resource pattern

The pattern we ship at Coding Droplets for production APIs with a team of 4+ engineers: controllers. Every time. The reason is not performance - it is refactoring safety and velocity for developers who did not write the original code.

Can You Mix Both?

Yes - and .NET 10 fully supports this. Minimal APIs and controllers coexist in the same ASP.NET Core application without conflict. A practical hybrid pattern:

  • Use Controllers for the main API surface (products, orders, users)
  • Use Minimal APIs for internal health checks, webhook receivers, or specialised high-throughput read endpoints

This is not an antipattern. It is a tool selection decision. The risk is inconsistency for developers navigating the codebase - so document the intent and keep the boundary clear.

Endpoint Filters vs Action Filters

One of the most important practical differences is cross-cutting concern implementation.

In controllers, you reach for action filters:

public class AuditFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context) { /* pre */ }
    public void OnActionExecuted(ActionExecutedContext context) { /* post */ }
}

In Minimal APIs, you use endpoint filters:

app.MapGet("/products", GetProducts)
   .AddEndpointFilter<AuditFilter>();

For simple pre/post logic, endpoint filters are clean. For complex pipelines with conditional short-circuiting, action filters have a more expressive model. The GitHub repo for Minimal API endpoint filters shows how reusable validation via endpoint filters works in practice - clone it and see the shape before committing to the pattern.

Is There a Clear Recommendation?

Yes - here is the decision I give teams:

Default to Controllers if:

  • Team has 3+ developers
  • API will have 20+ endpoints
  • You need rich filter pipelines
  • You value convention and navigability over minimum code

Choose Minimal APIs if:

  • Service has a deliberately small scope and will stay that way
  • Team is experienced and self-disciplined about organisation
  • You are building a microservice or background API, not a user-facing product API
  • You are trialling something fast and may throw it away

The worst outcome is choosing Minimal APIs because they look clean on day one, then fighting them 6 months later when the codebase has grown beyond what their organisational model handles gracefully.

FAQ

What is the performance difference between Minimal APIs and Controllers in ASP.NET Core?

In benchmarks from the ASP.NET Core team, Minimal APIs are marginally faster than controllers due to lower overhead in the routing and invocation pipeline. In practice the difference is negligible for most production APIs - measured in fractions of a millisecond per request. Do not choose based on raw throughput alone unless you are building ultra-high-throughput endpoints where every microsecond counts.

Can I use Minimal APIs and Controllers together in the same ASP.NET Core app?

Yes. Both coexist in the same application without conflict. A common pattern is to use Controllers for the primary API surface and Minimal APIs for internal or specialised endpoints like health checks or webhook receivers. Keep the boundary documented so developers know where each pattern is used.

Do Minimal APIs support OpenAPI / Swagger in .NET 10?

Yes. Starting with .NET 9, Microsoft shipped a new built-in OpenAPI document generation that works with Minimal APIs. In .NET 10, this support is first-class. You still need to call .WithOpenApi() on your route groups or endpoints to include them in the spec.

Do I get automatic model validation with Minimal APIs?

No - not by default. The [ApiController] attribute on controllers gives you automatic 400 responses on model validation failures. With Minimal APIs, you need to validate input manually (using FluentValidation, DataAnnotations, or a custom endpoint filter). This is one of the meaningful productivity gaps when coming from controllers.

Which is better for large enterprise APIs: Minimal APIs or Controllers?

For large enterprise APIs with many endpoints, multiple teams, and long-term maintenance requirements, Controllers are the safer choice. The convention-over-configuration model, automatic validation, richer filter pipelines, and clear organisational structure pay compound dividends as the codebase grows. Minimal APIs can work at scale but require strong team discipline around organisation.

Are Controllers deprecated in .NET 10?

No. Controllers are fully supported in .NET 10 and there are no plans to deprecate them. Microsoft's guidance is that both approaches are valid and supported long-term. Minimal APIs were introduced as an alternative, not a replacement.


About the Author

I'm Celin Daniel, Co-founder of Coding Droplets. I've been building .NET and ASP.NET Core systems in production for 13+ years - APIs, distributed backends, enterprise platforms. Everything I write here comes from real shipping experience: patterns that held up, trade-offs that bit us, and lessons learned the hard way.