Se uma chamada a um Durable Object terminasse em uma falha de rede, antes muitas vezes cabia a quem desenvolve decidir se deveria enviá-la novamente. Desde 5 de novembro de 2026, o runtime da Cloudflare executa parte dessas novas tentativas: ele repete automaticamente determinadas chamadas fetch() e RPC feitas por meio de um stub. Para o código da aplicação, a questão central agora é mais precisa: um método específico pode ser executado novamente com segurança?
A resposta depende de onde a conexão foi interrompida. O runtime repete automaticamente algumas chamadas, mantendo, por padrão, a proteção contra execução duplicada. Quando a entrega é incerta, ele usa o mesmo identificador de solicitação, e o objeto rejeita a nova tentativa se já tiver recebido a primeira. Um método marcado explicitamente com retryable() tem outro comportamento: pode ser executado novamente mesmo que a primeira tentativa já tenha chegado ao objeto. Por isso, essa marcação só é adequada para operações cuja repetição seja segura tanto para o estado quanto para os efeitos colaterais.
O que exatamente o runtime repete
De acordo com o anúncio da Cloudflare de 5 de novembro, as novas tentativas abrangem chamadas fetch() e RPC para Durable Objects feitas por um Worker ou outro Durable Object. Para chamadas por meio de um stub, o padrão prevê uma tentativa inicial e até quatro novas tentativas; nenhuma nova tentativa é iniciada mais de 10 segundos após o início da chamada.

A condição é um erro com a propriedade .retryable. Por exemplo, a solicitação pode não ter chegado ao objeto porque ele estava reiniciando ou sendo movido. O runtime também pode tentar novamente se a conexão cair e não for possível determinar se o objeto chegou a receber a solicitação. Se o objeto já a tiver recebido, a nova tentativa com o mesmo identificador será rejeitada. O runtime não repete erros lançados pelo código do Durable Object, erros com .overloaded nem respostas HTTP como 500: trata-se de uma resposta do handler, não de um erro de entrega.
Por que repetir a entrega não é o mesmo que repetir a operação
Reenviar uma solicitação, por si só, não significa executar o método uma segunda vez. Quando o resultado é incerto, o runtime envia a solicitação com o mesmo identificador; se o objeto tiver recebido a tentativa original, rejeita a nova. No modo normal, isso evita executar o método novamente — por exemplo, cobrar de novo ou criar um registro duplicado por causa de uma única falha de rede.

Esse limite muda quando o método é marcado com retryable(), de cloudflare:durable-objects. Nesse caso, o objeto pode executar o método novamente se a primeira tentativa já tiver começado. A Cloudflare dá dois exemplos: definir uma quantidade específica para um produto é idempotente; aumentar a quantidade em uma unidade não é. Repetir a primeira ação define o mesmo valor; repetir a segunda acrescenta mais uma unidade.
É preciso verificar não apenas o estado final do armazenamento, mas também todos os efeitos do método. Se uma nova execução criar outro pagamento, enviar uma mensagem ou iniciar uma ação externa, manter o mesmo estado dentro do Durable Object não torna a repetição segura. A marcação é adequada quando repetir não altera o significado do resultado nem duplica efeitos colaterais.
Quando a idempotência explícita é útil
Definir um valor, gravar um instantâneo do estado ou atualizar um campo para um valor conhecido costuma produzir o mesmo resultado quando repetido. Para esses métodos, retryable() pode permitir que a chamada seja concluída com sucesso após uma queda de conexão que ocorra depois do início do processamento.
Operações como “somar”, “criar mais um”, “cobrar” e “enviar” geralmente exigem outra proteção. Antes de permitir uma nova execução, confirme que a operação de negócio reconhece duplicatas ou foi concebida de modo que a repetição não crie um segundo efeito. O nome da função, por si só, não garante nada: verifique todas as alterações de estado e ações externas realizadas pelo método.
retryable() tem uma função restrita: permite executar novamente quando não é possível saber se a primeira chamada chegou ao destino. Não altera quais erros são tratados pelo runtime nem aumenta o número de tentativas. A marcação se aplica à função; uma versão sobrescrita ou envolvida do método não a herda automaticamente, a menos que também seja marcada explicitamente.
O que verificar em um projeto já em produção
O ponto mais provável para revisão são os próprios ciclos de novas tentativas em torno das chamadas a Durable Objects. Agora, cada tentativa pode incluir novas tentativas do runtime, então o total de chamadas pode ser maior do que o definido apenas pela aplicação. A Cloudflare recomenda reduzir o número de tentativas próprias ou definir maxRetries: 0 no stub se o código da aplicação for responsável por controlá-las.
Os limites de um stub específico são definidos ao chamar get() ou getByName(). O parâmetro maxRetries define de zero a dez novas tentativas após a primeira; timeoutMs define o intervalo após o qual não se iniciam mais tentativas, entre 500 e 60.000 milissegundos. Essas configurações se aplicam às chamadas feitas por meio desse stub. Os recursos retryable() e do objeto retry exigem o Wrangler 4.158.0 ou posterior.
Uma revisão útil consiste em responder a três perguntas para cada chamada: ela pode alterar o estado mais de uma vez? Vai repetir efeitos colaterais externos? A aplicação tem uma política própria de novas tentativas? Em seguida, decida se o stub deve usar os valores padrão ou limites personalizados. Para métodos idempotentes, avalie separadamente a marcação explícita; para os demais, mantenha a proteção e verifique o tratamento de erros quando o resultado da primeira tentativa for desconhecido.
Consequência: a responsabilidade passa para o limite do método
As novas tentativas automáticas retiram parte da lógica de rede do código da aplicação, mas decidir se uma nova execução é aceitável continua sendo uma propriedade da operação. O runtime pode repetir a entrega com segurança e parar quando não sabe se a chamada foi executada. Quem desenvolve pode permitir uma nova execução do método, confirmando explicitamente que ela não duplicará alterações de estado ou efeitos colaterais.
Por isso, vale entender a atualização como uma mudança no contrato entre a camada de transporte e o handler. Primeiro, verifique os próprios ciclos de novas tentativas e se os efeitos colaterais podem ser repetidos; depois, configure os limites nos stubs necessários. Assim, a resiliência integrada a falhas breves pode coexistir com o controle sobre operações em que uma segunda execução tem um custo real.