Software costuma imaginar o tempo como um número que cresce perfeitamente. Em produção, relógios derivam, jobs atrasam, mensagens chegam fora de ordem, retries duplicam ações e deploys interrompem workers. Um sistema confiável não pressupõe um relógio ideal. Ele define fonte autoritativa, incerteza permitida e comportamento quando algo executa cedo, tarde ou mais de uma vez.

Escolha o relógio para a pergunta

Wall clock responde quando ocorreu no mundo compartilhado. Monotonic clock responde quanto tempo passou no processo. Timeout baseado em wall clock pode falhar após correção para trás.

Deadlines de duração usam monotonic; eventos persistidos usam instants UTC documentados.

Expiração é uma política

now > expires_at não define sozinho inclusive boundary, clock skew ou grace period. Tokens podem tolerar segundos; reservas podem exigir decisão transacional.

Centralize a regra para que endpoints não discordem. Logs devem mostrar timestamps e política aplicada.

Jobs programados podem executar tarde

Scheduler torna o trabalho elegível, não garante execução imediata. Queue cheia, worker parado ou dependência indisponível causam atraso. O job precisa saber se ainda faz sentido.

Recurring jobs precisam de missed-run policy. Recuperar tudo pode sobrecarregar; ignorar tudo pode perder processamento importante.

Idempotência protege contra repetição

Timeout pode disparar retry depois de sucesso. Sem idempotência, surgem faturas, e-mails ou transferências duplicadas.

Operation ID, unique constraint e estado registrado tornam repetição segura. Exactly-once entre sistemas é difícil; safely retryable é mais realista.

Timestamp não garante causalidade

Serviços têm relógios diferentes e rede reordena mensagens. Ordenar apenas pelo timestamp cria uma história plausível, não necessariamente correta.

Use sequence, versão de domínio, transaction ou logical clock quando a ordem é crítica.

Injete tempo na lógica

Código que chama o relógio real em todo lugar é difícil de testar. Clock abstraction ou current instant explícito permite testar limites sem sleep.

Fake clocks avançam por decisão do teste, tornando casos de horas ou dias instantâneos e determinísticos.

Fronteiras críticas precisam de atomicidade

Verificar deadline na aplicação e atualizar depois cria race. Banco autoritativo deve comparar tempo e mudar estado na mesma transação.

Efeitos externos ainda precisam de idempotência e reconciliação. A transação não controla o provedor de pagamento.

Reconciliação encontra trabalho perdido

Jobs periódicos podem localizar registros vencidos, estados travados e operações incompletas. Reconciliação transforma falha temporária em atraso recuperável.

Ela deve ser segura para repetir. Projetá-la cedo é mais fácil que provar que nenhum timing path falhará.

Retries precisam conhecer o deadline

Uma tentativa útil para sincronização pode ser inválida depois da data limite de negócio. Cada attempt deve verificar se a ação ainda faz sentido.

Backoff, maximum attempts e dead-letter fazem parte da semântica temporal, não apenas da infraestrutura.

Leases e locks precisam de margem

Um worker que possui lease por 30 segundos pode perder o direito antes de terminar. Renovação, fencing token e relógio autoritativo evitam que dois workers acreditem possuir o mesmo recurso.

Confiar apenas em um timestamp local para exclusão distribuída é arriscado. O storage que concede o lease deve validar a versão ou token da posse.

Jobs atrasados podem precisar de compensação

Algumas ações não podem simplesmente ser executadas tarde nem descartadas. Um fechamento financeiro perdido pode exigir uma rotina de compensação, auditoria e aprovação humana. A política precisa existir antes do incidente.

Dead-letter queues devem ter owner, prazo e procedimento de replay. Acumular mensagens sem decisão apenas adia a falha.

Testes precisam de clock controlável

Além de fake clock, testes devem avançar através de boundaries: exatamente na expiração, um instante antes, um depois, mudança de dia e transição de timezone. Essas fronteiras concentram erros off-by-one.

Integration tests podem simular atraso de queue e retry duplicado. Dormir em tempo real não oferece a mesma determininação.

Capacity planning deve usar lag histórico

Tempo médio de execução não mostra picos de atraso. Percentis de queue wait e schedule lag revelam quando a capacidade deixa de atender deadlines. Histórico por horário ajuda a planejar workers antes de eventos sazonais.

Alertas devem usar objetivos do negócio. Um job de cobrança e uma limpeza de cache podem compartilhar infraestrutura, mas não o mesmo limite de atraso.

Recovery precisa de responsabilidade clara

Quando um job entra em dead-letter ou perde o deadline, alguém precisa decidir replay, compensação ou cancelamento. Sem owner e runbook, a fila vira arquivo de falhas esquecidas.

Uma boa arquitetura registra o motivo, estado anterior, operation ID e efeitos já executados para permitir uma recuperação segura.

Meça atraso, não só tamanho da fila

Queue depth não mostra há quanto tempo o trabalho espera. Meça schedule lag, queue wait, execution duration e age do item mais antigo.

O limite aceitável varia por processo. Um minuto pode ser crítico para um lease e irrelevante para relatório noturno.

Decisões precisam de auditoria

Ao expirar acesso ou ignorar job atrasado, registre clocks, timestamps, attempt e regra aplicada. Isso separa problema de scheduler, queue, relógio e domínio.

Um sistema temporal confiável não promete pontualidade perfeita. Ele detecta atraso, decide se ainda deve agir e recupera sem duplicar efeitos.