EC2, Lambda ou container: onde diabos eu coloco minha aplicação?
Colocar uma aplicação .NET no ar na AWS não tem uma resposta única, e faz sentido que não tenha: EC2, contêineres via ECS/Fargate e AWS Lambda resolvem o mesmo problema de hospedagem partindo de modelos de execução completamente diferentes.
A resposta curta
Se a carga de trabalho é uma API que fica no ar o tempo todo, com tráfego relativamente previsível, contêiner (ECS com Fargate) costuma ser o ponto de partida mais equilibrado. Se existe necessidade de controle total sobre o sistema operacional, EC2 ainda faz sentido. Se a carga é orientada a evento, esporádica ou com picos bem definidos, Lambda tende a sair mais barato e exigir menos operação.
Isso não é regra fixa, é ponto de partida.
EC2: controle total, responsabilidade total
Amazon EC2 fornece uma máquina virtual. A escolha do sistema operacional, a instalação do runtime do .NET, a configuração do servidor web, o patch de segurança e o escalonamento (manual ou via Auto Scaling Groups) ficam por conta de quem opera a aplicação. É o modelo com menos abstração e, por isso, o que dá mais liberdade para configurar exatamente o que for necessário, ao custo de mais responsabilidade operacional.
Faz sentido quando a aplicação depende de alguma configuração de sistema operacional específica, de um software instalado que não se encaixa bem em contêiner, ou quando a equipe já tem processo maduro de gerenciar VM e prefere manter esse controle.
Contêineres com ECS e Fargate: menos servidor para gerenciar
Amazon ECS é o orquestrador de contêineres da AWS. Rodar uma aplicação .NET nele significa empacotar a aplicação numa imagem de contêiner e descrever, numa task definition, como ela deve rodar: quanto de CPU, memória, quais portas expor.
A escolha que mais muda a experiência é o launch type. Com EC2 como launch type, ainda é preciso gerenciar as instâncias por trás dos contêineres. Com AWS Fargate, a AWS gerencia essa camada, e a preocupação passa a ser apenas a imagem e a definição da tarefa, sem provisionar servidor manualmente.
Esse modelo tende a equilibrar bem controle e operação para uma API tradicional, que fica no ar o tempo todo esperando requisição.
Lambda: paga por execução, mas não é gratuito em complexidade
AWS Lambda roda uma função sob demanda, cobrando por tempo de execução e não por servidor ligado. Isso é vantajoso para carga orientada a evento (processar uma mensagem de fila, responder a um upload no S3, executar uma tarefa agendada), onde manter um servidor ligado o tempo todo para atender eventos esporádicos seria desperdício.
O ponto que costuma pegar quem vem do mundo de aplicação web tradicional é o cold start: quando uma função não é chamada há um tempo, a próxima invocação precisa inicializar o ambiente de execução antes de processar a requisição, o que adiciona latência. Em .NET, isso historicamente pesava mais que em runtimes mais leves, e a compilação Native AOT ajuda a reduzir esse tempo de inicialização quando o cenário exige baixa latência mesmo em cold start.
Para uma API tradicional, síncrona, com tráfego constante o tempo todo, Lambda tende a fazer menos sentido que contêiner: o modelo de cobrança por execução perde vantagem quando o volume de chamadas já justificaria manter um servidor ligado o tempo inteiro de qualquer forma.
Uma comparação rápida
| Cenário | EC2 | ECS/Fargate | Lambda |
|---|---|---|---|
| Controle total do SO | Sim | Não | Não |
| Sem gerenciar servidor | Não | Com Fargate, sim | Sim |
| Cobrança por execução | Não | Não | Sim |
| Ideal para evento esporádico | Não | Não | Sim |
| Ideal para API sempre ativa | Depende | Sim | Depende do volume |
A pergunta que decide, na prática
Mais do que preferência entre os três, a pergunta que costuma decidir bem é: essa carga de trabalho fica ligada o tempo todo, esperando requisição, ou ela só existe quando algo específico acontece? A primeira aponta para EC2 ou contêiner. A segunda aponta para Lambda. Dali em diante, o resto é ajuste fino de custo e operação, não uma escolha certa ou errada de largada.