← voltar ao índice

· 5 min de leitura · por Tiago

Minimal APIs vs Controllers no .NET

Desde que as Minimal APIs foram introduzidas no .NET 6, uma dúvida virou recorrente nas equipes que trabalham com ASP.NET Core: devemos abandonar os Controllers tradicionais e migrar tudo para o novo modelo mais enxuto? A resposta, como quase sempre em arquitetura de software, é "depende". Neste post vamos destrinchar as diferenças reais entre as duas abordagens, os cenários em que cada uma brilha e como evitar decisões baseadas apenas em modismo.

O que mudou com as Minimal APIs

Antes das Minimal APIs, criar um endpoint HTTP em ASP.NET Core praticamente exigia um Controller: uma classe herdando de ControllerBase, atributos de rota, injeção de dependência via construtor e todo o pipeline de convenções do MVC por trás. Isso funciona muito bem, mas para APIs pequenas ou microsserviços com poucas responsabilidades, esse arcabouço todo pode parecer over-engineering.

As Minimal APIs propõem o oposto: você define rotas diretamente no Program.cs (ou em arquivos de extensão organizados por domínio), usando métodos como MapGet, MapPost, MapPut e MapDelete, sem precisar de uma classe dedicada. O resultado é um código mais direto, com menos "cerimônia" e startup mais rápido, características especialmente valiosas em ambientes serverless ou containers que precisam subir rapidamente.

var app = WebApplication.Create(args);

app.MapGet("/produtos/{id}", (int id, IProdutoService service) =>
{
    var produto = service.ObterPorId(id);
    return produto is not null ? Results.Ok(produto) : Results.NotFound();
});

app.Run();

Note que a injeção de dependência continua funcionando normalmente, só que via parâmetros do delegate em vez do construtor da classe.

Onde as Minimal APIs realmente ganham

O principal ganho das Minimal APIs está na simplicidade para cenários pequenos e bem delimitados. Alguns exemplos práticos:

  • Microsserviços enxutos: quando um serviço expõe dois ou três endpoints e não precisa de toda a estrutura de um Controller, o código fica mais legível sem a indireção extra.
  • Funções serverless e Azure Functions isolados: o menor overhead de inicialização é relevante quando o cold start impacta diretamente a experiência do usuário.
  • Protótipos e provas de conceito: escrever e validar uma ideia rapidamente, sem se preocupar com convenções de MVC, acelera a iteração.
  • APIs internas de baixa complexidade: ferramentas administrativas ou endpoints de suporte que não crescem muito ao longo do tempo.

Além disso, a performance de startup e o menor consumo de memória em cenários de alta densidade de containers (muitas instâncias pequenas rodando em Kubernetes, por exemplo) são argumentos técnicos concretos, não apenas estéticos.

Onde os Controllers ainda fazem mais sentido

Por outro lado, existem cenários em que abrir mão dos Controllers tradicionais custa caro em manutenibilidade:

  • APIs grandes e complexas: quando você tem dezenas ou centenas de endpoints, a organização em Controllers, com filtros, ActionFilters, ModelBinding customizado e convenções bem estabelecidas, evita que o Program.cs vire um arquivo de milhares de linhas difícil de navegar.
  • Uso intensivo de recursos do MVC: coisas como ApiController attribute (validação automática de model state), versionamento de API bem estruturado, ou content negotiation mais sofisticada ainda têm suporte mais maduro no modelo de Controllers.
  • Equipes grandes com padrões consolidados: se o time já tem uma convenção estabelecida em torno de Controllers, filtros e middlewares específicos, migrar para Minimal APIs pode gerar inconsistência sem ganho real.
  • Necessidade de testes de integração mais elaborados: embora ambos os modelos sejam testáveis, a estrutura de Controllers com suas convenções facilita certos padrões de teste que times já dominam.

Vale lembrar que as Minimal APIs também evoluíram bastante desde o lançamento: hoje já suportam filtros de endpoint, grupos de rotas (MapGroup), validação e até geração de OpenAPI de forma similar aos Controllers. Mas ainda existem lacunas em cenários muito específicos, como certas customizações de model binding mais avançadas.

Não é uma escolha binária

Um ponto importante: nada impede misturar as duas abordagens no mesmo projeto. É perfeitamente razoável ter Controllers para o núcleo mais complexo da aplicação e Minimal APIs para endpoints auxiliares, webhooks simples ou health checks. O ASP.NET Core foi desenhado para permitir essa convivência sem atrito.

Uma boa prática é pensar por bounded context ou módulo: se um determinado módulo do sistema é pequeno e estável, ele é candidato natural a Minimal APIs. Se é o coração do domínio, com regras de negócio complexas e muitos casos de borda, provavelmente vale manter a estrutura mais robusta dos Controllers.

Critérios práticos para decidir

Na hora de bater o martelo, algumas perguntas ajudam a guiar a decisão:

  1. Quantos endpoints esse serviço vai ter no médio prazo? Poucos favorecem Minimal APIs; muitos favorecem Controllers.
  2. A equipe já tem convenções fortes em torno de Controllers? Se sim, o custo de mudança de mentalidade pode não valer a pena.
  3. Startup time e footprint de memória são críticos? Se o serviço roda em ambiente serverless ou escala horizontalmente de forma agressiva, Minimal APIs tendem a ajudar.
  4. Existe necessidade de recursos avançados de model binding, filtros ou versionamento maduro? Controllers ainda têm vantagem aqui.
  5. O time valoriza mais simplicidade e menos abstração, ou prefere a organização explícita de classes e atributos? Isso é, em parte, uma questão de estilo e cultura de engenharia.

Conclusão

Minimal APIs e Controllers não são concorrentes que precisam de um vencedor absoluto: são ferramentas com propósitos que se sobrepõem parcialmente, mas que atendem bem a contextos diferentes. Para serviços pequenos, microsserviços enxutos ou cenários sensíveis a cold start, as Minimal APIs trazem simplicidade e performance sem abrir mão de recursos essenciais como injeção de dependência e documentação OpenAPI. Já para APIs grandes, com muitas regras de negócio e necessidade de recursos mais avançados do MVC, os Controllers continuam sendo a escolha mais sólida e testada pelo tempo.

O mais importante é evitar decidir por modismo em qualquer uma das direções. Avalie o tamanho do projeto, as necessidades reais de escalabilidade, a maturidade da equipe com cada abordagem e, sempre que fizer sentido, não tenha medo de combinar as duas dentro da mesma aplicação.

← voltar ao índice