Tell Me When Down
How it worksWhat we checkPricing
BlogFree toolsCompareDocs
Log inGet started
All posts
When cron fails silently

Why your Vercel cron job is not running

July 18, 2026·6 min read
A dark server streaming binary with a network cable plugged in — a scheduled job that never fired.

You added a cron job, deployed, and nothing happened. No run, no error, no log line. On Vercel this is almost never a mystery — it's one of a handful of rules that fail quietly, and they're easy to walk into.

Here are the reasons a Vercel cron job doesn't run, in rough order of how often they catch people — and how to tell which one is yours.

1×/day
max frequency on the Hobby plan
within the hour
when it actually fires — not on the minute
100
cron jobs per project, on every plan
prod only
crons run on production deployments, not previews

1. You're on Hobby and asked for more than once a day

This is the big one. On the Hobby plan, a cron job can run at most once per day. A schedule like */5 * * * * or 0 * * * * (every five minutes, every hour) isn't throttled — it fails the deployment outright with an error about the schedule.

If your deploy is failing, read the build error. If it deployed but never runs, the schedule that got through is a daily one, running once. To go more frequent you need Pro, or a different scheduler entirely.

2. It runs — just not when you think

A daily cron set for 0 9 * * * does not fire at exactly 09:00. Vercel invokes cron jobs at any point within the scheduled hour to spread load, so "it didn't run at 9" might just be a job that runs at 9:41. Give it the full hour before calling it dead.

3. Your CRON_SECRET check is rejecting the real cron

The recommended way to stop strangers hitting your cron URL is to set a CRON_SECRET environment variable. Vercel then calls your route with an Authorization: Bearer <CRON_SECRET> header, and you reject anything that doesn't match.

Get that comparison slightly wrong — a stray space, the wrong env, the secret set for Preview but not Production — and your own route returns 401 to Vercel on every invocation. The job fires on schedule and fails every single time, which reads in your head as "not running."

A cron that 401s or 500s is still running— Vercel did its part. The failure is inside your handler, and Vercel won't email you about it. You only see it if you check the logs or watch the endpoint.

4. It's not on a production deployment

Cron jobs only run on your production deployment. Testing on a preview branch, or never promoting the deploy that added the cron, means the schedule simply doesn't exist yet. Ship it to production and confirm the job shows up under the project's cron settings.

A route that fails loudly instead of silently

Most of the pain above comes from a handler that swallows its own errors. Write it so a bad secret or a thrown error returns a real error status, and set the schedule to something Hobby accepts. This prompt does both:

paste into Claude or ChatGPT
Write a Vercel Cron Job route for my Next.js App Router project and wire up the config.

Requirements:
- A GET route handler at app/api/cron/<name>/route.ts.
- At the top, verify the request came from Vercel Cron: read the Authorization header and compare it to "Bearer " + process.env.CRON_SECRET. If it doesn't match, return a 401 immediately.
- Only run the actual job after that check passes. Wrap the work in try/catch, log any error clearly, and return a 500 on failure so a broken run shows up instead of a fake 200.
- Give me the matching vercel.json "crons" entry with a once-per-day schedule (so it's valid on the Hobby plan) and explain how to change it if I upgrade to Pro.
- Remind me to set CRON_SECRET in my Vercel project's environment variables for Production, and that cron jobs only run on production deployments.

Show me both files in full.

For the full rules straight from the source, Vercel's cron jobs documentation lists the per-plan limits.

Catching the runs Vercel won't tell you about

Even a correct cron fails eventually — a downstream API dies, the secret gets rotated, a deploy breaks the route. Vercel schedules the job; it doesn't judge whether your run succeeded. That part is on you.

The durable fix is the same one that works for any scheduled job: have it ping a heartbeat on success and get alerted when the ping goes missing. Tell Me When Down watches for that silence, so a cron that started 500-ing at 3am reaches you before your users do.

Know when your cron fails — not just when Vercel fires it.

Join Tell Me When Down free and drop one heartbeat ping at the end of your job. If a run 401s, 500s, or never fires, you get an email in minutes instead of finding out from a missed charge or an empty table.

Watch my cron jobfree · no card required
more on when cron fails silently
How do I know if my cron job actually ran?"It ran" hides four different outcomes and only one is good. Why logs and error emails miss the worst case, and how a success heartbeat catches a job that never fired at all.Why your GitHub Actions scheduled workflow stopped runningGitHub auto-disables a scheduled workflow after 60 days of no repo activity — and the cron's own runs don't count as activity, so a quiet side project always trips it. Here's the rule, the fork gotcha, and the fix.Why your Supabase pg_cron job isn't runningA pg_cron job that never runs is usually a missing pg_net extension, a UTC-not-local schedule, or a run that fired and failed. Here's how to read the run log Postgres keeps and find which is yours.What a dead man's switch is (and when your app needs one)Most monitoring watches for something bad happening. A dead man's switch watches for something good not happening — the right tool for backups and cron jobs that fail silently. What it is, and when you need one.

spot something wrong or out of date? [email protected] — we'll fix it

Tell Me When Down

Uptime and security monitoring for people who'd rather ship than babysit servers. We watch so you can sleep.

product
How it worksWhat we checkPricingDocsBlogFAQ
free toolsWebsite security scanSupabase pause checkRender sleep checkMixed content checkerSecurity headers checkCookie security checkSSL expiry check
comparevs UptimeRobotvs Better Stackvs PingdomFor indie hackers
company
StatusAbout our botSupportPrivacyTerms
© 2026 TellMeWhenDown · tellmewhendown.com