3 de Abril de 2025
Bugs assíncronos e race conditions
Como entender falhas de timing deixando ordem, concorrência e estado compartilhado mais visíveis.
Andrews Ribeiro
Founder & Engineer
3 min Intermediario Sistemas
O problema
Race condition assusta porque quase nunca quebra exatamente do mesmo jeito duas vezes.
Funciona local, falha em produção, some quando você coloca console.log e aparece só quando duas respostas chegam em uma ordem especifica.
Isso faz muita gente tratar bug assíncrono como azar ou magia, quando o problema real e falta de controle sobre a ordem dos eventos.
Modelo mental
Para caçar bug assíncrono, olhar só para “o que o código faz” não basta.
Você precisa olhar para:
- a linha do tempo dos eventos
- qual operação termina antes da outra
- se o estado ainda era valido no momento em que a resposta chegou
Quando a investigação muda de “ler linha de código” para “desenhar a cronologia”, o bug para de parecer fantasma.
Também ajuda trocar uma frase ruim por uma melhor:
- ruim: “o sistema ficou doido”
- melhor: “duas operações terminaram em ordem diferente da que a UI assumia”
Quebrando o problema
Uma forma prática de capturar esse tipo de falha e esta:
- Liste os eventos concorrentes envolvidos.
- Desenhe a ordem em que eles podem terminar.
- Encontre o ponto em que duas operações disputam o mesmo estado.
- Descubra qual garantia arquitetural faltou: cancelamento, lock, id de request ou validação final.
Isso transforma bug “aleatorio” em colisao previsivel.
Essa parte importa porque concorrência não significa bagunca total. Significa que existem várias linhas do tempo validas, e o seu código precisa continuar correto em mais de uma delas.
Exemplo simples
Imagine uma busca com autocomplete:
- o usuário digita
re - a requisição A sai
- ele continua e digita
react - a requisição B sai
- a requisição B responde rápido e mostra o resultado certo
- a requisição A responde atrasada e sobrescreve a tela com resultado velho
O problema aqui não e o fetch.
O problema e que o frontend aceitou uma resposta velha como se ela ainda fosse a verdade atual.
As soluções maduras aqui sao claras:
- cancelar a requisição anterior com
AbortController - ignorar resposta com id antigo
- atualizar a tela só se a resposta ainda corresponder ao texto atual
Nenhuma dessas soluções existe para “deixar o fetch mais rápido”. Elas existem para impedir que uma resposta antiga ganhe o direito de escrever em um estado que já mudou.
Erros comuns
- Tentar reproduzir o bug clicando aleatoriamente sem mapear a linha do tempo.
- Colocar
setTimeoutpor cima do problema e torcer. - Assumir que assíncrono significa aleatorio e impossivel de consertar.
- Esquecer que duas respostas validas podem destruir a UI se chegarem na ordem errada.
Como um senior pensa
Quem tem mais experiência não chama bug assíncrono de “flaky” por reflexo.
Desenha a cronologia e pergunta:
“Que sequência de eventos coloca o sistema em um estado inválido?”
Essa pergunta tira a conversa da supersticao e coloca em causalidade.
Também costuma aparecer outra pergunta boa:
“Qual garantia esta faltando para impedir que esse estado velho volte a valer?”
As vezes a resposta e cancelamento. As vezes e idempotencia. As vezes e lock. As vezes e simplesmente checar se o estado ainda continua valido antes de aplicar o resultado.
O que o entrevistador quer ver
Em entrevista de frontend ou sistemas, concorrência expõe profundidade rápido.
- Você entender que concorrência quebra previsibilidade por natureza.
- Você procurar ponto de colisao sobre estado mutavel compartilhado.
- Você falar em garantias arquiteturais, não só em espalhar
await.
Uma resposta forte costuma soar assim:
“Eu desenharia a linha do tempo e tentaria descobrir qual resposta ou operação chegou tarde demais e ainda assim conseguiu gravar no estado compartilhado. A partir disso, eu escolheria a garantia certa: cancelamento, lock, versão, id de request ou validação final.”
Race condition não e azar. E uma colisao que a arquitetura ainda não sabe suportar.
Resumo rápido
O que vale manter na cabeça
- Bug assíncrono fica mais claro quando você desenha a ordem dos eventos, não só o código.
- Race condition acontece quando duas operações validas disputam o mesmo estado sem garantia suficiente.
- Cancelamento, id de request, validação final e lock sao formas diferentes de proteger o estado certo.
- Quanto mais cedo você nomeia a colisao, menos tempo perde chamando o bug de aleatorio.
Checklist de pratica
Use isto ao responder
- Consigo desenhar a linha do tempo de duas requisicoes concorrentes?
- Sei dizer se a correção pede cancelamento, lock, id de request ou validação final?
- Consigo explicar por que resposta antiga não pode sobrescrever estado novo?
- Sei falar de bug assíncrono em entrevista como problema de causalidade, não de azar?
Você concluiu este artigo
Próximo passo
Como debugar com método Próximo passo →Compartilhar esta página
Copie o link manualmente no campo abaixo.