Vercel Cron vs Posthook: Static vs Dynamic Scheduling

Compare Vercel Cron Jobs and Posthook for scheduling on Next.js. Vercel Cron handles fixed recurring tasks with no retries. Posthook handles both dynamic and recurring scheduling with delivery tracking, retries, and anomaly detection.

Last updated: March 24, 2026

Vercel Cron Jobs and Posthook solve different scheduling problems. Vercel Cron handles fixed recurring tasks defined at deploy time — a cron expression in vercel.json that fires on a schedule you know in advance. Posthook handles dynamic scheduling decided at runtime — a user signs up and you schedule a reminder for 24 hours from now, or a trial starts and you schedule an expiration check for 14 days out.

The distinction matters because most scheduling work in a production application is not fixed-cadence. It is event-driven: something happens in your app, and you need something else to happen later. “Send this user a reminder in 24 hours” is one API call with Posthook and fundamentally impossible with Vercel Cron. “Expire this trial 14 days after signup” requires a polling workaround with Vercel Cron — a cron job scanning a database every minute — and a single scheduling call with Posthook. “Retry a failed payment next Tuesday at 10am in the user’s timezone” is not expressible with Vercel Cron at all.

If your only scheduling need is a handful of fixed recurring tasks and you want zero configuration, Vercel Cron is the simpler choice. But once scheduling decisions depend on runtime events, Posthook is the tool that fits the problem. And for recurring work, Posthook Sequences offer more power and reliability than Vercel Cron Jobs — calendar scheduling with DST handling, dependency graphs between steps, and config-as-code with diff and apply.

At a glance

DimensionVercel CronPosthook
Scheduling modelStatic cron expressions in vercel.json, set at deploy timeDynamic API calls at runtime — schedule anything when the event happens
One-time future schedulingNot supportedFirst-class — postAt (UTC timestamp), postAtLocal + timezone (DST), postIn (relative delay)
Dynamic schedulingRequires redeployment to change schedulesCore design — schedule from any API route or server action
Recurring schedulingCron expressions (UTC only)Sequences with calendar scheduling, DST handling, dependency graphs, onDays/onDates, config-as-code
Delivery targetYour own Vercel routes onlyAny HTTP endpoint or WebSocket
Delivery methodHTTP GETHTTP POST (or WebSocket)
Retries on failureNone — failed invocations are not retriedConfigurable backoff (fixed, exponential, jitter), per-hook overrides
Timezone / DSTUTC onlyUTC, local timezone with automatic DST handling, relative delays
PrecisionHobby: up to 59 minutes late. Pro: within the minuteSecond-level precision
ObservabilityFunction logs — 1-hour retention (Hobby), 1-day (Pro)Dashboard with per-hook delivery inspection and attempt history
AlertingNonePer-endpoint anomaly detection with email, Slack, and webhook notifications
Incident responseNone — no replay, no bulk retryBulk retry, cancel, or replay filtered by time range, endpoint, or sequence
Delivery guaranteeDocs warn cron events may fire more than onceAt-least-once delivery — duplicates are rare but possible; handlers should be idempotent
InfrastructureZero — built into VercelAPI key + endpoint
CostIncluded with Vercel plan (counts as function invocations)Free tier (1K hooks/mo), Launch $39/20K, Growth $99/100K
Best fitFixed recurring tasks on known schedules — daily cleanup, cache warming, periodic syncDynamic per-event scheduling — reminders, expirations, retries, follow-ups, timezone-aware delivery

How Vercel Cron Jobs work

Vercel Cron Jobs are built into the Vercel platform. You define cron expressions in vercel.json, and Vercel triggers an HTTP GET to a route in your production deployment on the specified schedule. The feature is built on Amazon EventBridge Scheduler.

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

This is a clean model for simple recurring tasks:

  • Zero configuration cost — add the cron expression, deploy, and it works. No separate service, no API key, no billing relationship.
  • Native Vercel integration — cron jobs appear in the Vercel dashboard. As of March 2026, you can manually trigger a cron job from the deployment summary.
  • 100 cron jobs per project on all plans (raised January 2026).
  • Built on reliable infrastructure — Amazon EventBridge Scheduler handles the scheduling under the hood.

The limits are worth understanding clearly:

  • Hobby plan: once per day maximum frequency, and invocations can arrive up to 59 minutes late.
  • Pro plan: once per minute frequency, within the specified minute.
  • Production deployments only — cron jobs do not run in preview or development environments.
  • No retries — if a cron invocation fails, Vercel does not retry it. The failure appears in function logs and disappears after 1 hour (Hobby) or 1 day (Pro).
  • UTC only — no timezone or DST support.
  • No programmatic creation — schedules are defined in vercel.json and require a redeployment to change.
  • Possible duplicate execution — Vercel’s documentation warns that cron events may be delivered more than once.

For fixed-cadence tasks where these constraints are acceptable — daily reports, periodic cache warming, hourly data sync — Vercel Cron is the right tool. It is simple and free.

The dynamic scheduling gap

The limitation is not that Vercel Cron is unreliable at what it does. The limitation is that most scheduling work in a production application is not fixed-cadence.

Consider three common patterns:

Send a reminder 24 hours after signup. Each user signs up at a different time. You need a timer for each signup event, not a single recurring schedule. Vercel Cron cannot express this.

Expire a trial 14 days after activation. Each trial starts on a different date. With Vercel Cron, the common workaround is a cron job that runs every minute, queries the database for trials that should have expired, and processes them. This is the polling anti-pattern — it works, but it scales poorly, wastes compute on empty runs, and becomes its own operational surface: what happens when the query is slow, or the function times out, or the database is temporarily unreachable? The cron job has no retry logic, so the expired trials sit unprocessed until the next run.

Retry a failed payment next Tuesday at 10am in the user’s timezone. This requires scheduling a specific future time, in a specific timezone, with DST handling. Vercel Cron is UTC-only and has no concept of per-event scheduling or timezone-aware delivery.

These are not edge cases. They are the core scheduling problems in most SaaS applications. Vercel Cron was designed for a different job — and it does that job well.

How Posthook works

Posthook is a managed scheduling service. You schedule a hook via API — specifying a target endpoint, a delivery time, and an optional payload — and Posthook handles persistence, delivery, retries, and observability.

For a Next.js developer, the integration looks like this:

import Posthook from "@posthook/node";

const posthook = new Posthook("phk_...");

// Schedule a reminder 24 hours from now
await posthook.hooks.schedule({
  path: "/api/hooks/send-reminder",
  postIn: "24h",
  data: { userId: "user_abc", type: "onboarding" },
});

// Schedule a trial expiration at a specific time
await posthook.hooks.schedule({
  path: "/api/hooks/expire-trial",
  postAt: "2026-04-06T00:00:00Z",
  data: { trialId: "trial_xyz" },
});

// Schedule in the user's local timezone (DST-safe)
await posthook.hooks.schedule({
  path: "/api/hooks/payment-retry",
  postAtLocal: "2026-03-31T10:00:00",
  timezone: "America/New_York",
  data: { paymentId: "pay_123" },
});

Your handler receives the delivery as an HTTP POST and decides what to do:

// app/api/hooks/expire-trial/route.ts
export async function POST(req: Request) {
  const { data } = await req.json();
  const trial = await db.trials.findById(data.trialId);

  // Handler checks state — act or skip
  if (!trial || trial.status !== "active") {
    return Response.json({ skipped: true });
  }

  await db.trials.expire(trial.id);
  await sendTrialExpiredEmail(trial.userId);

  return Response.json({ expired: true });
}

No polling. No cron job scanning a database. Each event creates its own timer, and Posthook delivers it at the right time.

Key capabilities for Next.js teams:

  • Three scheduling modespostAt for exact UTC timestamps, postAtLocal + timezone for user-local scheduling with automatic DST handling, postIn for relative delays
  • Configurable retries — fixed, exponential, or jitter backoff with per-hook overrides at scheduling time
  • Built-in anomaly detection — per-endpoint failure rate tracking against historical baselines, with alerts via email, Slack, or webhook when failure rates spike
  • Incident response — bulk retry, cancel, or replay failed hooks filtered by time range, endpoint key, or sequence ID
  • Async hooks for reliable long-running work — your endpoint returns 202 Accepted immediately, offloads processing, and calls back via ack/nack URLs when done. Configurable timeouts up to 3 hours. Your Vercel function handles the handoff quickly; the actual work runs wherever you need it to
  • Sequences — recurring workflows with calendar scheduling, dependency graphs, and config-as-code via posthook.toml

Tradeoffs

Where Vercel Cron wins

  • Zero configuration. Add a cron expression to vercel.json and deploy. No API key, no SDK, no additional service to integrate.
  • No additional cost. Cron invocations count as Vercel function calls. There is no separate billing relationship.
  • No external dependency. Scheduling lives with your deployment. No third-party service to evaluate, onboard, or monitor.
  • Native ecosystem integration. Cron jobs appear in the Vercel dashboard, can be triggered manually from the deployment summary, and work within the Vercel deployment model.
  • Simple mental model. If the schedule is “run this every day at 8am UTC,” a cron expression is the most direct way to express it.

Where Posthook wins

  • Dynamic scheduling. Schedule anything at runtime based on application events. No redeployment, no polling, no scanning a database for work. Each event creates its own timer.
  • Retries. Vercel Cron has zero retry capability — if an invocation fails, it is gone. Posthook retries with configurable backoff and per-hook overrides. Every attempt is logged with status, response, and error details.
  • Timezone-aware scheduling. postAtLocal with a timezone handles DST transitions automatically. Vercel Cron is UTC-only — no concept of “10am in the user’s timezone.”
  • Observability and alerting. Dashboard with per-hook delivery inspection, attempt history, and per-endpoint anomaly detection with multi-channel alerts. Vercel Cron function logs expire after 1 hour on Hobby and 1 day on Pro.
  • Incident response. One API call retries all failed hooks in a time range. With Vercel Cron, a missed invocation is simply missed — there is no replay mechanism.
  • Delivery to any endpoint. Vercel Cron sends HTTP GET to your own Vercel routes. Posthook delivers HTTP POST (or WebSocket) to any endpoint — your own routes, external services, or private networks.
  • Precision. Second-level delivery precision. Vercel Cron Hobby can arrive up to 59 minutes late.
  • Async hooks. Your endpoint returns 202 immediately, offloads the work, and calls back when done — with up to 3-hour timeouts. The Vercel function handles the handoff quickly; the actual processing runs wherever makes sense for your architecture.

When Posthook replaces Vercel Cron entirely

Posthook Sequences cover everything Vercel Cron does for recurring work — and more:

  • Calendar scheduling with DST handling. Sequences schedule by calendar time in any timezone. Vercel Cron is UTC-only, so a “9am daily” job drifts by an hour across DST transitions.
  • Flexible recurrence patterns. onDays, onDates, and negative dates (e.g., -1 for last day of month) express schedules that cron syntax cannot.
  • Dependency graphs between steps. Multi-step recurring workflows where step B runs after step A completes. Vercel Cron has no concept of step ordering or dependencies.
  • Per-delivery retries. Every Sequence step retries on failure with configurable backoff. Vercel Cron does not retry at all.
  • Delivery tracking and anomaly detection. Every Sequence delivery is tracked with status, response, and attempt history. Anomaly detection alerts you when failure rates change. Vercel Cron has short-lived function logs and no alerting.
  • Config-as-code. Define Sequences in posthook.toml with diff, validate, and apply across environments. Vercel Cron expressions live in vercel.json and require redeployment to change — but there is no diff, no validation, and no multi-environment support.

The only reason to keep Vercel Cron alongside Posthook is free-tier quota conservation. If you have simple daily tasks and want to save your Posthook hook quota for dynamic scheduling, leaving those tasks on Vercel Cron is a reasonable choice. But it is an optimization, not a capability gap.

When to choose each

Choose Vercel Cron when:

  • You need a handful of fixed recurring tasks on a known schedule
  • The schedule is defined at deploy time and rarely changes
  • You are on Vercel and want zero additional configuration
  • Hobby-tier daily precision or Pro-tier minute precision is acceptable
  • You do not need retries, delivery tracking, or failure alerting
  • The tasks call your own Vercel routes, not external endpoints

Choose Posthook when:

  • Scheduling decisions happen at runtime based on user actions or application events
  • You need one-time future scheduling — “send this in 24 hours,” “expire this in 14 days”
  • You need per-user or per-event scheduling at any scale
  • You need retries with backoff when a delivery fails
  • You need timezone-aware scheduling with DST handling
  • You need observability, failure alerting, or delivery inspection
  • You want recurring workflows with more power than cron expressions — calendar scheduling, dependency graphs, config-as-code
  • You need to deliver to external endpoints, not just your own Vercel routes

Frequently asked questions

Ready to get started?

Create your free account and start scheduling hooks in minutes. No credit card required.