Back to blog

Guides · May 8, 2026

How to schedule tasks in v0 apps (the missing scheduler)

v0 ships Next.js apps to Vercel, and in 2026 the Vercel Hobby cron minimum is once per day, not once per hour. The classic `0 * * * *` expression now fails deployment outright. Here is the 5-minute pattern v0 users actually run to schedule a task on any cadence, in any timezone, without a redeploy.
crontap.com / blog
v0 ships Next.js apps to Vercel, but the scheduling story is messy in 2026: Vercel Hobby cron is now once-per-day minimum, so the classic "every hour" cron expression fails deployment outright. Here is the 5-minute pattern v0 users on Hobby (and Pro) actually run to schedule a task on any cadence, in any timezone, without a redeploy.

You used v0 to ship a Next.js app. The deploy to Vercel was one click. The site looks great. Now you want it to run a cleanup every 5 minutes, or send a daily email at 9am, or sync something from Stripe every hour. You opened vercel.json, added a cron entry, pushed, and the deploy failed with no helpful error. Vercel Hobby cron is now once-per-day minimum in 2026. The well-known "hourly minimum" stories from 2024 are out of date. Here is the pattern v0 users on Hobby (and Pro) actually run to schedule a task without a redeploy, in any timezone, on any cadence.

If you just want the short version: keep your v0-generated route, drop the crons entry from vercel.json, and point Crontap at the route URL with a bearer token. The scheduling lives outside the deploy, the cadence is a dropdown in the dashboard, and the timezone is per schedule.

You used v0 to build a Next.js app and pressed Publish. Now you want it to run something on a schedule.

This is the exact moment most v0 users find out about Vercel Cron. The agent already scaffolded a route handler at app/api/something/route.ts. The route works when you hit it from the browser. But it does not run on its own, and there is no "schedule this" button in the v0 chat or in the v0 project dashboard.

The Vercel docs you find first tell you to add a crons array to vercel.json and redeploy. You do that. The deploy fails. Or it succeeds and then your schedule shows up listed as something different than what you typed. Either way, the v0 user is now reading Vercel docs about cron jobs in 2026, which is the moment this post starts being useful.

Note before you continue: the stories online from 2023 and 2024 that say "Vercel Hobby cron is once an hour" describe an older limit. The new floor is once per day. The change matters because 0 * * * * ("every hour at minute 0") was the canonical low-cadence example, and it no longer deploys.

Why v0 does not ship a scheduler (and why Vercel Cron is awkward on Hobby)

v0's job is to scaffold a Next.js app and a one-click deploy. The schedule lives downstream, in Vercel. Vercel Cron exists, but the limits in 2026 push almost every "I want it to run every 5 minutes" use case off the Hobby plan.

v0 ships Next.js code with route handlers; deploy is one click to Vercel

The v0 deployments docs describe the shape: v0 writes Next.js code, you click Publish, the code lands as a Vercel project. Anything you can call over HTTPS, you have. That includes the route handlers v0 generates under app/api/*/route.ts. They work fine. They just have no clock attached.

Vercel Hobby cron is now once-per-day minimum

Per the Vercel Cron usage and pricing docs, the Hobby cron minimum in 2026 is once per day. A cron expression like 0 * * * * (every hour) is no longer valid on Hobby and fails the deploy with a validation error before the build even starts. The smallest cadence Hobby accepts is daily.

If you came here from a 2024 tutorial that says "Vercel Hobby is hourly", that tutorial is out of date. We cover the historical context (and the Pro tier story) in the existing Vercel cron hourly limit post.

Vercel Pro is $20 per seat per month, and v0 has its own bill

Vercel Pro lifts the cron limit to per-minute cadence, but it costs $20 per seat per month and every cadence change still ties to a redeploy because the cron entry lives in vercel.json. v0 itself is per-token billed on top of that. So a "5-minute cron on the app I built with v0" is two paid concerns running in parallel, with the cron change being the slower of the two (you have to ship a new build to change a single cron expression).

Per-schedule timezone is still UTC only

Vercel Cron is UTC across every tier. "9am local" in Europe/London cannot be expressed in vercel.json. You compute the right UTC offset yourself, and the offset drifts twice a year when daylight saving switches over.

The 60-second fix (use the v0-generated route as a webhook)

The structural fix is to take scheduling out of Vercel and put it somewhere that doesn't tie cadence to deploys, doesn't gate sub-daily on a $20 seat, and doesn't ignore timezones.

Crontap (cron)  →  HTTPS POST  →  Your v0 /api/cron route  →  the actual work

Vercel still owns the runtime. The clock moves outside.

Step 1: prompt v0 to add a route

Open the v0 chat for your project and ask for the endpoint you want fired on a schedule. Something like: "Create /api/cron/route.ts that pulls recent Stripe charges and emails me a summary, and verify an Authorization header against process.env.CRON_SECRET."

v0 will scaffold the route handler. A reasonable shape looks like:

export async function POST(request: Request) {
  const auth = request.headers.get("authorization");
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response("Unauthorized", { status: 401 });
  }
 
  await runDailyDigest();
  return Response.json({ ok: true });
}

Three things to note:

  1. POST so a casual GET from a crawler can't fire it.
  2. Authorization header instead of a query string token, so the secret never lands in access logs.
  3. Returns 200 quickly. If the work is slow, kick it off as a background task and return immediately.

Step 2: deploy via Publish and copy the URL

Click Publish in v0 (or push the connected repo). Once the deploy is live, copy the route URL. It looks like https://your-app.vercel.app/api/cron or your custom domain plus the path. This is the URL Crontap will hit on a schedule.

Step 3: add the secret to Vercel

Generate a strong random string locally:

openssl rand -base64 32

Add it as CRON_SECRET in your Vercel project under Settings, Environment Variables. Hit Save and redeploy once so the variable lands in production. Now the route refuses any anonymous traffic.

Step 4: create the schedule in Crontap

Head to Crontap and click New schedule.

  1. URL: paste the route URL from Step 2.
  2. Method: POST.
  3. Headers: add Authorization: Bearer <your CRON_SECRET>. Crontap stores the value encrypted.
  4. Cadence: type plain English like "every 5 minutes" or paste a cron expression. Crontap previews the next 5 fires inline.
  5. Timezone: pick the IANA zone the schedule actually means. Europe/London for the 9am UK digest, America/New_York for the 9am US digest, UTC for anything that is genuinely UTC.
  6. Failure alerts: turn on email or a webhook (Slack, Discord, Telegram) so 4xx and 5xx ping you the moment they happen.

Press Perform test. Crontap fires one real POST to the URL. If you see 200, you are done. If you see 401, the bearer is mismatched. If you see 5xx, the route failed and the alerting just proved itself.

Fix this in 60 seconds with Crontap. Free forever tier. Three schedules. No credit card. Schedule your first job →

What about Vercel Cron on Pro, or Upstash QStash, or Inngest?

External cron is a shape, not a religion. Three alternatives show up in v0 community threads. They all work; the trade-offs differ.

Vercel Cron on Pro

Works, but cadence changes are redeploys because the schedule lives in vercel.json. Every cadence tweak is "edit file, open PR, deploy". The timezone is still UTC. And Pro is $20 per seat per month before any cron exists.

Upstash QStash

QStash is Vercel's own recommended workaround in their v0 community thread on this exact question. It is a real message queue with retries and dead-letter handling on top of scheduling. Great if you need durable queueing. More setup than you need if you just want a clock pointing at a URL.

Inngest

Inngest gives you durable workflows, retries, fan-out, and scheduling in one product. Powerful for complex multi-step jobs. For "fire one URL every 5 minutes", it is more product than the job requires, and you bring your own Inngest account.

For a single recurring URL call, the external cron pattern is the smallest answer.

Real things teams schedule on v0 apps

A few shapes that come up over and over in v0 builds.

Hourly user notification sweep

A queue of users to nudge ("your trial ends in 3 days", "you have unread items"). The route reads the queue and sends in chunks. Crontap fires the route every hour in the customer's local timezone.

Daily Stripe subscription sync

Every night at 03:00 UTC the route pulls active subscriptions from Stripe, reconciles them against the local database, and posts any drift to Slack. One Crontap schedule, one bearer token, no vercel.json cron entry to fail your next deploy.

Every-5-minutes booking reminder check

The route looks for bookings in the next 30 minutes that have not had a reminder sent, sends the reminders, marks the rows. Crontap fires */5 * * * * in the IANA zone of the customer base. No DST math, no UTC offset spreadsheet.

Cache warm-up against the v0-deployed app

Hit the slow pages of the v0 site every 10 minutes so the next real visitor gets a warm response. The route is a simple fetch loop over a list of URLs. Crontap fires it on the cadence you want, you can pause it on quiet weekends without a deploy.

FAQ

Will Vercel Cron run on the Hobby plan at all?

Yes, but only at once-per-day cadence as of 2026. Per the Vercel Cron usage and pricing docs, sub-daily cron is gated to Pro and Enterprise. The cron expression must fire at most once every 24 hours on Hobby or the deploy fails validation.

How do I avoid breaking my deploy with a sub-daily cron in vercel.json?

Don't put a sub-daily cron in vercel.json on Hobby. Either drop the crons block entirely and let Crontap fire the route, or upgrade to Pro and accept the redeploy-per-change shape. The Vercel Cron quickstart shows the vercel.json syntax if you do go the Vercel-native route.

Does the v0 free plan let me publish at all?

Yes, v0 publishes to Vercel on the free plan. The scheduling story is independent of v0's own pricing; the constraint you hit is Vercel's cron tier, not v0's.

Can Crontap fire production but not preview?

Yes. Crontap fires whatever URL you give it. Point one schedule at your-app.vercel.app (production) and a second schedule (paused or on a slower cadence) at the preview URL. Each schedule has its own cadence, timezone, and bearer token.

Move the clock out of vercel.json. Free forever tier. Three schedules. No credit card. Schedule your first job →

References

Related on Crontap

From the blog

Read the blog

Guides, patterns and product updates.

Tutorials on scheduling API calls, webhooks and automations, plus deep dives into cron syntax, timezones and reliability.

Alternatives

Vercel Cron every minute: beating the Hobby hourly limit

Vercel Cron caps Hobby at hourly cadence and 5 jobs, and ties every change to a redeploy. Here is the external cron pattern teams use to ship per-minute schedules, per-IANA timezones, and one dashboard across projects without paying $20/mo per user for Pro.

Alternatives

Cloud Run cron without Cloud Scheduler

Cloud Scheduler costs $0.10 per job per month after the first 3 and asks for OIDC plus IAM bindings on every target. Here is the IAM-free pattern Cloud Run teams use to fire their .run.app URLs on a clock with one bearer token and one dashboard across every GCP project.