Sistemas distribuídos, 29/10/2026, 8 min de leitura

Cuidados com @Async em sistemas distribuídos cheios de integrações

O @Async devolve o controle rápido, mas troca a garantia de execução por uma promessa em memória que some quando o pod cai.

Colocar @Async num método é a forma mais barata de "deixar para depois". Em um sistema com muitas integrações, esse depois tem custo.

O que você perde sem perceber

Durabilidade. A tarefa vive numa fila em memória do pod. Se o pod reiniciar em um deploy ou por falta de memória, o trabalho pendente some, sem erro e sem registro.

Exceções. Em métodos void, a exceção não chega a quem chamou. Sem um AsyncUncaughtExceptionHandler, ela vira apenas uma linha de log.

@Async
public void notificarParceiro(Pedido p) {
    parceiroClient.enviar(p); // falhou? ninguém sabe
}

Contexto. Usuário autenticado, transação, MDC de log e correlation id ficam na thread original. Na thread assíncrona eles não existem, a menos que você os propague.

O pool é parte do design

Se você não configurar, o Spring Boot fornece um executor padrão, com fila praticamente ilimitada. Sob carga, a fila cresce até a memória acabar, em vez de aplicar contrapressão. Configure um pool com limites e uma política de rejeição explícita:

@Bean
public Executor integracaoExecutor() {
    var ex = new ThreadPoolTaskExecutor();
    ex.setCorePoolSize(8);
    ex.setMaxPoolSize(16);
    ex.setQueueCapacity(200);
    ex.setThreadNamePrefix("integracao-");
    ex.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    return ex;
}

Use pools separados por integração. Uma integração lenta não deve esgotar as threads das outras.

Quando @Async não é a ferramenta

Se perder a tarefa é inaceitável, o trabalho precisa passar por algo durável: uma fila de mensagens, ou o padrão outbox. O @Async serve para trabalho descartável ou refazível, como cache e métricas.

Checklist

  • O trabalho pode ser perdido? Se não, use fila.
  • Quem trata a falha? Ela é observável?
  • O pool tem limite e política de rejeição?
  • O contexto necessário está sendo propagado?
  • A operação é idempotente para o caso de reexecução?