Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Cron Jobs no Node.js: agendamento confiável

Atualizado em: 26 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Cron Jobs no Node.js executam tarefas recorrentes como fechamento diário, limpeza de dados, geração de relatórios e sincronização. O desafio não é interpretar a expressão cron, mas garantir que a tarefa rode no horário correto, apenas na quantidade desejada, com idempotência, observabilidade e recuperação de falhas.

Um scheduler dentro do processo é simples, porém cada réplica da aplicação pode executar o mesmo job. Reinícios também podem perder horários. Para produção, defina explicitamente quem agenda, quem executa e onde o estado fica persistido.

Expressão cron

# minuto hora dia-do-mês mês dia-da-semana
0 3 * * *

Esse exemplo executa diariamente às 03:00 no fuso configurado. Algumas bibliotecas aceitam campo de segundos; outras não. Documente o formato usado.

Scheduler básico

import cron from 'node-cron';

cron.schedule('0 3 * * *', async () => {
  await executeDailyCleanup();
}, {
  timezone: 'America/Sao_Paulo'
});

O exemplo funciona em uma instância, mas precisa de coordenação quando há múltiplas réplicas.

Fuso horário

Escolha entre UTC e fuso de negócio. UTC simplifica infraestrutura. Um fuso local é necessário quando a regra depende de calendário regional.

Horário de verão pode criar horários inexistentes ou repetidos. Defina o comportamento esperado e teste transições. Não dependa do fuso padrão do servidor.

Idempotência por janela

Crie uma chave estável para cada execução.

const executionKey = `daily-close:${tenantId}:2026-10-26`;

Persista a chave com constraint única.

CREATE TABLE scheduled_executions (
  job_name text NOT NULL,
  scope_key text NOT NULL,
  scheduled_for timestamptz NOT NULL,
  status text NOT NULL,
  started_at timestamptz,
  completed_at timestamptz,
  PRIMARY KEY (job_name, scope_key, scheduled_for)
);

Se duas instâncias tentarem inserir a mesma execução, apenas uma vence.

Coordenação com Advisory Lock

const acquired = await client.query(
  'SELECT pg_try_advisory_xact_lock($1) AS acquired',
  [jobLockKey]
);

if (!acquired.rows[0].acquired) return;

O lock evita concorrência imediata, mas a tabela de execução registra histórico e idempotência. Consulte Advisory Locks no Node.js.

Scheduler separado do worker

Uma arquitetura robusta divide responsabilidades:

  1. scheduler calcula horários;
  2. persiste um job;
  3. worker consome a fila;
  4. execução é idempotente;
  5. resultado fica registrado.

Assim, reiniciar o scheduler não interrompe jobs já criados.

Misfire e execução perdida

Se a aplicação estava desligada às 03:00, defina uma política:

  • executar assim que voltar;
  • ignorar a janela;
  • executar somente se o atraso for menor que um limite;
  • recalcular períodos pendentes.

Não deixe a decisão implícita na biblioteca.

Jobs longos

Uma tarefa pode durar mais que o intervalo. Escolha entre:

  • impedir sobreposição;
  • permitir paralelismo por tenant;
  • cancelar a execução anterior;
  • enfileirar a próxima;
  • coalescer várias janelas.

Para a maioria dos fechamentos e sincronizações, impedir sobreposição é mais seguro.

Timeout

await executeWithDeadline(
  () => generateReport(params),
  30 * 60 * 1000
);

Timeout deve cancelar operações internas quando possível. Apenas rejeitar uma Promise não interrompe automaticamente banco, HTTP ou subprocesso.

Retries

Faça retry apenas para falhas transitórias, com backoff e limite. Uma regra inválida ou credencial revogada precisa de intervenção.

Veja Retry com Backoff no Node.js.

Multi-tenancy

Não execute todos os tenants em uma única transação. Liste tenants com paginação e crie jobs independentes.

for await (const tenant of listTenantsInPages()) {
  await queue.add('monthly-close', {
    tenantId: tenant.id,
    period
  }, {
    jobId: `monthly-close:${tenant.id}:${period}`
  });
}

Isso permite retries e limites por tenant. Consulte Multi-Tenancy no Node.js.

Calendário de negócio

“Último dia útil” não cabe em uma expressão cron simples. Agende uma verificação diária e use calendário persistido para decidir se a tarefa deve rodar.

Backfills

Execuções retroativas devem usar o mesmo caminho do job normal, com uma chave de período diferente. Limite concorrência para não competir com tráfego de produção.

Deploys

Durante rolling deploy, versões antigas e novas coexistem. O payload do job deve ser versionado e compatível. Migrations precisam funcionar com ambos os workers.

Graceful shutdown

Ao receber sinal, pare de agendar novas execuções. Jobs em andamento devem concluir ou voltar para estado recuperável.

Consulte Graceful Shutdown no Node.js.

Observabilidade

Registre:

  • job e versão;
  • horário planejado e real;
  • atraso de início;
  • duração;
  • tentativas;
  • resultado;
  • itens processados;
  • próxima execução.

Alertas importantes incluem job que não iniciou, duração acima do normal, falhas repetidas e fila atrasada.

Painel operacional

Ofereça histórico, filtros, replay auditado e cancelamento seguro. Não permita disparar jobs administrativos sem autorização forte.

Testes

  • expressão e timezone;
  • mudança de horário;
  • duas instâncias;
  • execução duplicada;
  • aplicação desligada;
  • job mais longo que intervalo;
  • timeout;
  • retry;
  • shutdown;
  • backfill.

Use relógio injetável em testes; não dependa do horário real.

Erros comuns

  • rodar scheduler em todas as réplicas sem lock;
  • não persistir execução;
  • ignorar timezone;
  • não definir misfire;
  • permitir sobreposição acidental;
  • retry infinito;
  • job sem timeout;
  • uma transação para todos os tenants;
  • não monitorar execução ausente.

Checklist

  • timezone explícito;
  • chave idempotente;
  • coordenação distribuída;
  • estado persistido;
  • política de misfire;
  • sobreposição definida;
  • timeout e retry;
  • payload versionado;
  • shutdown gracioso;
  • histórico e alertas.

Conclusão

Cron Jobs no Node.js exigem mais que uma expressão de calendário. Em produção, tarefas recorrentes precisam de coordenação, idempotência e histórico persistido.

Separe agendamento de execução, defina timezone e misfire e monitore atrasos. Com locks, filas e jobs versionados, tarefas periódicas continuam confiáveis durante falhas e deploys.

Consulte a documentação de Timers do Node.js e a documentação do node-cron.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita