← Back to Blog
Guide schedule vercel cron serverless

A Vercel Cron Alternative Without the Plan Limits

Daily-only on Hobby, no retries, and every run burns a function invocation. The limits are fine until they aren't — here's the outside-in approach.

JW

Jason Warner

July 27, 2026

A Vercel Cron Alternative Without the Plan Limits

Vercel Cron is a tidy piece of integration. One entry in vercel.json, deploy, and your route runs on a schedule:

{
  "crons": [
    { "path": "/api/daily-report", "schedule": "0 9 * * *" }
  ]
}

No infrastructure, nothing else to manage. For a lot of projects that's the end of the story, and it should be. But the constraints are real, and they tend to show up in a fairly predictable order.

The Order You Hit Them In

Frequency comes first. On Hobby, cron jobs run once a day, at a time Vercel picks within the hour you asked for. Want something every fifteen minutes — a queue drain, a sync, a health check — and you're on Pro before you've shipped anything.

Then job count, because the Hobby allowance fills faster than you'd think. Every recurring task wants one.

Then the function timeout, which catches people out because it's not obvious the cron job is subject to it. A nightly export that grows past the limit starts failing at exactly the point where you have enough data to care, and the fix is restructuring the job into chunks.

Then the absence of retries. If an invocation fails — a transient database error, a cold start that ran long, a dependency having a bad thirty seconds — that run is gone. It runs again at the next scheduled time, which for a daily job means a 24-hour hole.

Then observability, or the shape of it. You get function logs, and logs are good at telling you what happened when a run ran. They're a poor instrument for noticing a run that didn't happen at all.

And eventually cost, quietly. Every execution is an invocation on your account. A one-minute health check is north of 40,000 invocations a month for a request whose entire job is confirming something is awake.

The Thing Underneath All of Them

Those are symptoms. The design decision producing them is that the schedule lives inside the deployment.

Your cron config sits in vercel.json, so changing a schedule means shipping a deploy — and rolling back a bad release rolls back your cron configuration along with it, which is a genuinely surprising way to lose a job. The scheduler can also only ever call your own Vercel functions, so the moment you need to hit a third-party API on a timer, it can't help you at all.

Scheduling From Outside

Move the schedule out and call the endpoint over HTTP. Your route handler doesn't change:

schedule: */15 * * * *
timezone: Europe/London
method:   POST
url:      https://your-app.vercel.app/api/daily-report
headers:  Authorization: Bearer <secret>
retries:  3
timeout:  60s

You get whatever frequency you want on whatever plan you're on, because the scheduler isn't your host. Failures retry with backoff instead of waiting a day. Run history keeps the status, duration, and response body. Missed-run alerts tell you when a window passed with no success, which is the thing logs can't show you. Auto-disable stops a broken job from hammering a dead endpoint indefinitely. Schedules change without a deploy. And you can point it at any URL, not just your own functions.

Lock the Route Down

Once the endpoint is callable from the internet, it needs a guard. A shared secret in a header is the usual approach:

export async function POST(req: Request) {
  const auth = req.headers.get('authorization');
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response('unauthorized', { status: 401 });
  }
  await runDailyReport();
  return new Response('ok');
}

Worth doing even if you stay on Vercel Cron, incidentally. An unauthenticated cron route is a public endpoint anyone can trigger as often as they like.

What This Doesn't Fix

Moving the scheduler out doesn't lengthen your function timeout. If the job honestly needs ten minutes, no external scheduler changes that — you either split the work into pieces that fit, or have the endpoint kick off a background job and return immediately.

What does change is the consequence of failure. With retries, a failed run gets another attempt in a couple of minutes instead of leaving a silent gap until tomorrow.

When to Stay Put

On Pro, with a stable schedule, a quick job, and no real cost to an occasional missed run — use Vercel Cron. It's one config entry and there's nothing else to think about, which counts for a lot.

Reach for Bluejay Schedule when you need sub-daily frequency without upgrading, retries, alerting on runs that never happened, schedules that change without a deploy, or jobs that call something other than your own functions. Hosted cron scheduler vs server cron covers the broader comparison.


Schedule serverless jobs without the plan limits. Start free with Bluejay Schedule.

#schedule #vercel #cron #serverless

Schedule your first HTTP job with confidence

Set up in minutes. Free to start.

Start scheduling free