Excelente artigo! A análise detalhada da pipeline do Roslyn até o ILCompiler e a explicação dos trade-offs reais é o tipo de conteúdo técnico que mais agrega valor.
Essa discussão do Native AOT toca numa mudança de paradigma muito interessante que vai além do ecossistema .NET: a transição de dependência de reflexão em tempo de execução para Source Generators em tempo de compilação.
Embora muitos devs vejam a perda de reflexão dinâmica como um ponto negativo do AOT, do ponto de vista de robustez e determinismo isso é uma evolução arquitetural enorme. Forçar que serializadores (System.Text.Json) e injeções de dependência resolvam seus contratos em tempo de compilação elimina classes inteiras de bugs silenciosos em produção.
O ponto onde o Native AOT brilha de verdade não é apenas o tempo de startup de 10ms em serverless, mas a previsibilidade da pegada de memória (memory footprint estável sem flutuações de compilação JIT Tier 0 / Tier 1 sob carga) e a facilidade de gerar CLIs e binários únicos autocontidos para distribuição sem exigir o runtime instalado na máquina do usuário.
Parabéns pela profundidade técnica do guia e por desmistificar que AOT não é bala de prata, mas sim uma decisão consciente de engenharia baseada em trade-offs!
Obrigado pelo comentário, trsthales! Fico muito contente que o artigo tenha te agregado.
Você resumiu muito bem um ponto que eu deveria ter dado mais peso: Native AOT não é só sobre ganhar milissegundos no startup. A previsibilidade de memória e de latência, a eliminação do trabalho de JIT em runtime e a distribuição de um binário autocontido também entram forte nessa conta, principalmente quando há muitas instâncias ou processos curtos.
E concordo bastante com a leitura sobre source generators. Eles não substituem toda reflexão, mas ajudam a deslocar uma parte importante dos problemas para o build, onde fica mais fácil detectar e corrigir. Para serialização e cenários conhecidos de DI, esse determinismo é uma vantagem arquitetural bem concreta.
O comentário do maniero também me fez perceber que deixei a conclusão rígida demais. A escolha precisa considerar o objetivo e as métricas da aplicação, não apenas o rótulo dela. Vou revisar essa parte para deixar isso mais claro e incluir memória, previsibilidade e operação ao lado de startup e throughput.
Valeu por complementar a discussão de um jeito tão certeiro!