Serverless hosting removes the server, and with it the place your background work used to live. A request handler can’t spend ninety seconds generating a report, retry a failed webhook tomorrow, or run something every night at 3am — and reaching for Redis, a queue, a worker process, and a cron container undoes most of the reason you went serverless.

Inngest puts that machinery behind an HTTP endpoint you already have. You write functions; it remembers state, retries with backoff, sleeps for a week if you ask, and shows you every run.

A function

  npm install inngest
  
  import { Inngest } from "inngest";
export const inngest = new Inngest({ id: "my-app" });

export const onSignup = inngest.createFunction(
  { id: "welcome-sequence", retries: 4 },
  { event: "user/signed.up" },
  async ({ event, step }) => {
    await step.run("send-welcome", () =>
      sendEmail(event.data.email, "welcome")
    );

    await step.sleep("wait-three-days", "3d");

    const active = await step.run("check-activity", () =>
      hasCreatedProject(event.data.userId)
    );

    if (!active) {
      await step.run("send-nudge", () => sendEmail(event.data.email, "getting-started"));
    }
  }
);
  
  await inngest.send({ name: "user/signed.up", data: { userId, email } });
  

Every step.run is checkpointed. If the third step throws, the first two are not repeated — they’re replayed from memory — and the failing one retries with backoff. step.sleep costs nothing while it waits, so a three-day delay is not a process sitting idle.

That checkpointing is the whole idea: a multi-day workflow written as one readable function, running on hosting that forgets everything between requests.

Scheduled work

  export const nightly = inngest.createFunction(
  { id: "nightly-report" },
  { cron: "0 3 * * *" },
  async ({ step }) => { /* ... */ }
);
  

Cron without a machine to run it on — and unlike your platform’s cron trigger, a failure retries and is visible in a run log with the arguments and the error.

  npx inngest-cli@latest dev      # local dev server with the full UI
  

Where it fits

JobGood fit?
Onboarding and drip sequencesYes — the sleep-and-branch pattern
Webhook processing with retriesYes
Report generation, exports, importsYes
Nightly cleanup and reconciliationYes
Fan-out across thousands of itemsYes, with concurrency and throttle controls
Sub-100ms work in the request pathNo — just do it inline
Very high-throughput streamingNo — that’s Kafka’s job

The free tier covers a real side project indefinitely; check the current run limits before you build something high-volume on it. Trigger.dev is the closest alternative, your cloud provider’s queue plus a worker is the DIY route, and Inngest can also be self-hosted if you’d rather own it.

One habit that saves you later

Make every step idempotent. Retries are the feature, which means each step may run more than once: send-with-an-idempotency-key, upsert instead of insert, check before you charge. A retry that emails a customer twice is the bug this tool will find in your code.

Next

Users need to be findable, and so does your content → Meilisearch

Last updated 25 Aug 2026, 00:00 UTC. history