Build reliable background jobs and workflows with Inngest. Use when a user asks to run background tasks, create event-driven workflows, build reliable job queues, set up step functions for long-running processes, schedule recurring jobs, handle webhook processing, build multi-step async workflows, add retries and error handling to background jobs, or replace BullMQ/Celery with a serverless-friendly alternative. Covers event sending, function definition, step orchestration, retries, scheduling, and fan-out patterns.
You are an expert in Inngest, the event-driven durable workflow engine for TypeScript. You help developers build reliable multi-step workflows, scheduled jobs, and event-driven functions with automatic retries, step-level caching, fan-out/fan-in patterns, rate limiting, and debouncing — running on any serverless platform (Vercel, Netlify, AWS Lambda, Cloudflare) with zero infrastructure to manage.
// inngest/functions/onboarding.ts
import { inngest } from "./client";
export const onboardUser = inngest.createFunction(
{
id: "onboard-user",
retries: 3,
concurrency: [{ limit: 10 }], // Max 10 concurrent executions
},
{ event: "user/signed-up" },
async ({ event, step }) => {
// Step 1: Create account (cached — won't re-run on retry)
const user = await step.run("create-account", async () => {
return await db.users.create({
email: event.data.email,
name: event.data.name,
});
});
// Step 2: Send welcome email
await step.run("send-welcome", async () => {
await resend.emails.send({
to: user.email,
subject: "Welcome!",
react: WelcomeEmail({ name: user.name }),
});
});
// Step 3: Wait 24 hours (durable — survives deployments)
await step.sleep("wait-for-activation", "24 hours");
// Step 4: Check if user activated
const activated = await step.run("check-activation", async () => {
const u = await db.users.findById(user.id);
return u.activatedAt !== null;
});
if (!activated) {
// Step 5: Send reminder
await step.run("send-reminder", async () => {
await resend.emails.send({
to: user.email,
subject: "Complete your setup",
react: ReminderEmail({ name: user.name }),
});
});
}
return { userId: user.id, activated };
},
);
// Fan-out: process items in parallel
export const processBatch = inngest.createFunction(
{ id: "process-batch" },
{ event: "batch/uploaded" },
async ({ event, step }) => {
const items = event.data.items;
// Fan-out — run up to 10 items in parallel
const results = await Promise.all(
items.map((item, i) =>
step.run(`process-item-${i}`, () => processItem(item))
),
);
// Fan-in — aggregate results
const summary = await step.run("summarize", () => ({
total: results.length,
success: results.filter(r => r.status === "ok").length,
failed: results.filter(r => r.status === "error").length,
}));
return summary;
},
);
// Scheduled (cron)
export const dailyCleanup = inngest.createFunction(
{ id: "daily-cleanup" },
{ cron: "0 3 * * *" }, // 3 AM daily
async ({ step }) => {
const deleted = await step.run("cleanup-expired", async () => {
return await db.sessions.deleteWhere({ expiresAt: { lt: new Date() } });
});
return { deletedSessions: deleted };
},
);
// Send events from anywhere
import { inngest } from "./client";
// From API route
app.post("/api/signup", async (req, res) => {
const user = await createUser(req.body);
await inngest.send({
name: "user/signed-up",
data: { email: user.email, name: user.name, userId: user.id },
});
res.json(user);
});
// Batch events
await inngest.send([
{ name: "order/created", data: { orderId: "1" } },
{ name: "order/created", data: { orderId: "2" } },
]);
export const syncCRM = inngest.createFunction(
{
id: "sync-crm",
debounce: { period: "5m", key: "event.data.userId" }, // Wait 5min, take latest
rateLimit: { limit: 100, period: "1h" }, // Max 100/hour
},
{ event: "user/updated" },
async ({ event, step }) => {
await step.run("sync", () => crm.upsertContact(event.data));
},
);
npx inngest-cli@latest init
npx inngest-cli@latest dev # Local dev server with UI
step.run() is cached; if the function retries, completed steps are skippedPromise.all with indexed step names for parallel processinginngest dev for a visual dashboard showing function runs, events, and step detailsnpx skills add TerminalSkills/inngest下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer