Recipe

Inngest Primer

Inngest is a durable execution engine for queueing, scheduling, and retrying background work triggered by events. This primer walks through wiring Inngest into a Meridian-powered Next.js app so long-running LLM jobs survive crashes, deploys, and rate limits without losing state.

1. Install and mount the handler

Add the SDK, then expose a Next.js route handler that Inngest can poll. The handler is the single entry point that registers every function you define. Keep it inapp/api/inngest/route.tsso the platform can discover it automatically.

// app/api/inngest/route.ts
import { serve } from "inngest/next";
import { inngest } from "@/inngest/client";
import { summarize } from "@/inngest/summarize";

export const { GET, POST, PUT } = serve({
  client: inngest,
  functions: [summarize],
});

2. Define a step-based function

Each step.run call is a checkpoint. Inngest persists the return value, so a retry resumes from the last successful step instead of replaying expensive Meridian completions. Wrap every model call, DB write, and external API request in its own step.

import { inngest } from "./client";

export const summarize = inngest.createFunction(
  { id: "summarize-thread", retries: 3 },
  { event: "thread/summarize.requested" },
  async ({ event, step }) => {
    const doc = await step.run("fetch", () =>
      fetch(event.data.url).then(r => r.text())
    );
    const summary = await step.run("meridian", () =>
      meridian.chat({ model: "azure/model-router", input: doc })
    );
    return { summary };
  }
);

3. Trigger from a server action

Fire events from anywhere on the server. The send call returns immediately and Inngest takes ownership of the job. The client polls the handler for new work, so local dev requires runningnpx inngest-cli devalongside next dev.

await inngest.send({
  name: "thread/summarize.requested",
  data: { url: "https://example.com/thread/42" },
});