npx skills add ...
npx skills add sickn33/agentic-awesome-skills --skill inngest
Inngest expert for serverless-first background jobs, event-driven
npx skills add sickn33/agentic-awesome-skills --skill inngest
Inngest expert for serverless-first background jobs, event-driven workflows, and durable execution without managing queues or workers.
Inngest function with typed events in Next.js
When to use: Starting with Inngest in any Next.js project
// lib/inngest/client.ts import { Inngest } from 'inngest';
export const inngest = new Inngest({ id: 'my-app', schemas: new EventSchemas().fromRecord(), });
// Define your events with types type Events = { 'user/signed.up': { data: { userId: string; email: string } }; 'order/placed': { data: { orderId: string; total: number } }; };
// lib/inngest/functions.ts import { inngest } from './client';
export const sendWelcomeEmail = inngest.createFunction( { id: 'send-welcome-email' }, { event: 'user/signed.up' }, async ({ event, step }) => { // Step 1: Get user details const user = await step.run('get-user', async () => { return await db.users.findUnique({ where: { id: event.data.userId } }); });
} );
// app/api/inngest/route.ts (Next.js App Router) import { serve } from 'inngest/next'; import { inngest } from '@/lib/inngest/client'; import { sendWelcomeEmail } from '@/lib/inngest/functions';
export const { GET, POST, PUT } = serve({ client: inngest, functions: [sendWelcomeEmail], });
Complex workflow with parallel steps and error handling
When to use: Processing that involves multiple services or long waits
export const processOrder = inngest.createFunction( { id: 'process-order', retries: 3, concurrency: { limit: 10 }, // Max 10 orders processing at once }, { event: 'order/placed' }, async ({ event, step }) => { const { orderId } = event.data;
} );
Functions that run on a schedule
When to use: Recurring tasks like daily reports or cleanup jobs
export const dailyDigest = inngest.createFunction( { id: 'daily-digest' }, { cron: '0 9 * * *' }, // Every day at 9am UTC async ({ step }) => { // Get all users who want digests const users = await step.run('get-users', async () => { return await db.users.findMany({ where: { digestEnabled: true }, }); });
} );
// Separate function handles individual digest sending export const sendDigest = inngest.createFunction( { id: 'send-digest', concurrency: { limit: 50 } }, { event: 'digest/send' }, async ({ event, step }) => { // ... send individual digest } );
Safely process webhooks with deduplication
When to use: Handling Stripe, GitHub, or other webhooks
export const handleStripeWebhook = inngest.createFunction( { id: 'stripe-webhook', // Deduplicate by Stripe event ID idempotency: 'event.data.stripeEventId', }, { event: 'stripe/webhook.received' }, async ({ event, step }) => { const { type, data } = event.data;
} );
Multi-step AI processing with chunked work
When to use: AI workflows that may take minutes to complete
export const processDocument = inngest.createFunction( { id: 'process-document', retries: 2, concurrency: { limit: 5 }, // Limit API usage }, { event: 'document/uploaded' }, async ({ event, step }) => { // Step 1: Extract text (may take a while) const text = await step.run('extract-text', async () => { return await extractTextFromPDF(event.data.fileUrl); });
} );
Severity: CRITICAL
Message: Inngest requires a serve handler to receive events
Fix action: Create app/api/inngest/route.ts with serve() export
Severity: ERROR
Message: Ensure all Inngest functions are registered in the serve() call
Fix action: Add function to the functions array in serve()
Severity: WARNING
Message: Step names should be kebab-case and descriptive
Fix action: Use descriptive step names like 'fetch-user' or 'send-email'
Severity: ERROR
Message: waitForEvent should have a timeout to prevent infinite waits
Fix action: Add timeout option: { timeout: '24h' }
Severity: WARNING
Message: Consider adding concurrency limits to protect downstream services
Fix action: Add concurrency: { limit: 10 } to function config
Severity: WARNING
Message: Inngest client should define event schemas for type safety
Fix action: Add schemas: new EventSchemas().fromRecord()
Severity: CRITICAL
Message: Every Inngest function must have a unique ID
Fix action: Add id: 'my-function-name' to function config
Severity: WARNING
Message: step.sleep should use duration strings like '1h' or '30m', not milliseconds
Fix action: Use duration string: step.sleep('wait', '1h')
Severity: WARNING
Message: Consider configuring retry policy for failure handling
Fix action: Add retries: 3 or retries: { attempts: 3, backoff: { ... } }
Severity: ERROR
Message: Payment-related functions should use idempotency keys
Fix action: Add idempotency: 'event.data.orderId' to function config
Skills: inngest, nextjs-app-router, vercel-deployment
Workflow:
Skills: inngest, ai-agents-architect, supabase-backend
Workflow:
Skills: inngest, stripe-integration, backend
Workflow:
Skills: inngest, email-systems, supabase-backend
Workflow:
Skills: inngest, backend, analytics-architecture
Workflow:
Works well with: nextjs-app-router, vercel-deployment, supabase-backend, email-systems, ai-agents-architect, stripe-integration
1. Trigger event from user action (inngest)
2. Schedule drip emails with step.sleep (inngest)
3. Send emails with retry (email-systems)
4. Track email status (supabase-backend)1. Define cron triggers (inngest)
2. Implement processing logic (backend)
3. Aggregate and report data (analytics-architecture)
4. Handle failures with alerting (inngest)