All guides

LEARN \u00b7 DEBUGGING GUIDE

Cron job not running in production: how to debug scheduled tasks

You set up a cron job to run every hour. It works when you trigger it manually. But the scheduled run never happens. Users are not getting their daily reports. Something is stopping the scheduler.

IntermediateDocker/deployment debugging

What this usually means

Scheduled jobs depend on a scheduler process being alive and correctly configured. If the scheduler process is not running (crashed, not deployed as a separate process, or scaled to zero by the platform), no jobs fire. If the timezone is wrong, the job fires but at an unexpected time. If the schedule expression has a typo, the job might fire once a month instead of once an hour. Platform-specific cron (Vercel Cron Jobs, GitHub Actions schedule, Render Cron Jobs) have their own configuration that is separate from the application code.

( 01 )Fast diagnosis

The first ten minutes \u2014 establish facts before touching code.

  • 1Check if the scheduler process is running. In production, is there a dedicated worker/clock process? Is it up?
  • 2Check the cron schedule expression. `0 * * * *` means every hour at minute 0. `* 0 * * *` means every minute at hour 0. Easy to mix up.
  • 3Check the timezone. The cron schedule might be in UTC but you expect it in your local timezone, or vice versa.
  • 4Check the platform's cron job dashboard (Vercel, Render, GitHub Actions). Does it show recent executions? Any failed attempts?
  • 5Check if the deployment platform scales to zero. If the app has no traffic, the scheduler process might be shut down.
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchPlatform cron dashboard (Vercel Cron Jobs, Render Cron Jobs, GitHub Actions schedule)
  • searchScheduler process status — `ps aux | grep cron`, `pm2 list`, Kubernetes CronJob status
  • searchCron schedule expression in code or config
  • searchApplication timezone configuration — `TZ` env var, server timezone
  • searchCron job logs — check the platform's log output for execution attempts
  • searchDeployment configuration — is the scheduler deployed as a separate service?
  • searchEnvironment variables — does the cron job need env vars that are not set in the scheduler environment?
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningScheduler process is not running — crashed, not deployed, or scaled to zero
  • warningCron schedule expression is wrong (minute vs hour confusion, wrong day of month)
  • warningTimezone mismatch: schedule is in UTC but you think it is local time
  • warningPlatform cron is configured but not enabled or is in a paused state
  • warningCron job fails on first run and the scheduler gives up (no retry logic)
  • warningDeployment wipes the scheduler config during a restart
  • warningEnvironment variables required by the job are not available in the scheduler context
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildAdd a health check endpoint that reports the scheduler status and last execution time
  • buildLog every cron job execution start and end with timestamps — even if the job has no work to do
  • buildSet the timezone explicitly in the cron config or use UTC consistently everywhere
  • buildUse a dedicated scheduler process (e.g. a separate dyno, container, or function) that does not scale to zero
  • buildAdd monitoring and alerting for missed cron executions
  • buildTest the cron schedule by setting it to run every minute temporarily and verifying execution
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedSet the cron schedule to run every minute temporarily. Confirm it executes in production.
  • verifiedCheck the scheduler logs — a start-of-execution log should appear at the expected time.
  • verifiedTrigger the job manually and verify the logic works — separate 'scheduler not firing' from 'job logic broken'.
  • verifiedAfter fixing, monitor the next scheduled execution and confirm it runs.
  • verifiedSet up an alert if a scheduled job misses its expected run window.
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningNot having a dedicated scheduler process — relying on the web process to also run scheduled tasks
  • warningNot testing scheduled jobs in a production-like environment
  • warningAssuming the cron schedule expression is correct without testing it
  • warningNot logging execution attempts — zero visibility into whether the scheduler is even trying
  • warningNot setting up alerting for missed executions