Your cron jobs should do more than run.

Schedule functions that sleep, fan-out, parallelize, retry, and recover. Trace every run with step-level observability.

Did your cron finish?

Platform-specific cron jobs all have the same problem: they fire and forget. You have no idea if the job succeeded, how long it took, or why it failed at 3am.

  • No observability

    Did it finish? Was the output correct? You shouldn't have to build custom logging to know.

  • No retries

    If your cron fails halfway through, it's gone. Wait until the next scheduled run, or write recoveries.

  • No directives

    Traditional crons can't sleep mid-function, fan-out to parallel jobs, or cancel a scheduled run based on business logic.

  • Can't do more than run

    Traditional crons can't sleep mid-function, fan-out to parallel jobs, or cancel a scheduled run based on business logic.

In Practice

Replace your setup with one line of code

A single trigger in your existing codebase can replace your entire cron setup. Inngest handles scheduling, retries, timezone support, and observability.

inngest/functions/weekly-digest.ts
// Runs every Friday at 12pm Paris time — with full observability and retries
export const weeklyDigest = inngest.createFunction(
{ id: "weekly-digest" },
{ cron: "TZ=Europe/Paris 0 12 * * 5" },
async ({ step }) => {
// Load all users — this step retries independently if it fails
const users = await step.run("load-users", async () =>
db.query("SELECT * FROM users")
);
// Fan-out: send one event per user, triggering parallel email jobs
await step.sendEvent(
"fan-out-digests",
users.map(u => ({
name: "app/send.weekly.digest",
data: { user_id: u.id, email: u.email }
}))
);
// Done — each email job runs in parallel with its own retries
}
);
// Dynamic scheduling: run at a user-defined time
export const sendReminder = inngest.createFunction(
{ id: "send-reminder" },
{ event: "reminder/scheduled" },
async ({ event, step }) => {
// Sleep until the user-specified timestamp, then run
await step.sleepUntil("wait-for-time", event.data.remindAt);
await step.run("send-notification", () =>
notify(event.data.userId)
);
}
);

Why modern teams choose Inngest for scheduled jobs

Everything forproduction pipelines

  • Fan-out at scale

    Send an array of events from within your cron. Each one spawns an independent job with its own retries. No batching logic needed.

    See Docs
  • Serverless-first

    Scheduled jobs run on your existing deployment. No dedicated workers, no separate infrastructure — just your code, invoked on schedule.

    See Docs
  • Schedule in timezones

    Use TZ=America/New_York prefix in your cron expression. Inngest handles DST and timezone math so your jobs run when your users expect.

    See Docs
  • Cancel before firing

    A function sleeping until tomorrow can be automatically cancelled the moment a matching event arrives. No stored job IDs.

    See Docs
  • Mix cron and events

    Trigger functions by schedule and/or event; run your daily report automatically, or trigger on demand.

    See Docs
  • Full visibility into every run

    See execution history, step-level traces, and failure reasons for every run. No more guessing if your cron fired.

    See Docs

What teams have built with Inngest to handle cron & scheduled jobs

FAQ

  • Inngest is not just a cron service. It adds durable, step-based execution to scheduled jobs — so if a scheduled job fails mid-run, only the failed step retries, not the whole job.

  • Yes. You define a schedule directly in code using a cron expression, and Inngest triggers execution on time. No separate cron daemon, server, or infrastructure required.

  • Inngest queues missed runs and executes them as soon as your deployment is available. Runs are never silently skipped.

  • Yes. Inngest triggers scheduled jobs via HTTP, so they run on any serverless platform without a persistent process. Vercel's built-in cron limits don't apply.

  • Yes. A single event sent to Inngest can fan out to multiple functions running in parallel, each with their own retries and execution state. No custom pub/sub logic required.

  • Yes. A single Inngest function can be triggered by a cron schedule and an event. You can run a daily report automatically and trigger it immediately on demand without duplicating logic.

  • Every scheduled run has a full execution trace in the Inngest dashboard — start time, step duration, failures, and output. You don't need to dig through logs to confirm execution.