inngest について
inngest は、Inngest を使ったサーバーレスのバックグラウンドジョブやイベント駆動ワークフローの構築を支援するスキルです。永続化されたステップ、リトライ、スケジュール、並行実行を扱います。
主な機能
- 01イベント駆動の関数
- 02永続化された複数ステップ実行
- 03リトライと並行実行制御
- 04スケジュール実行とWebhookワークフロー
- 05イベントのファンアウトパターン
活用シーン
- 01遅延を伴うオンボーディングメールの送信
- 02複数サービスにまたがる注文処理
- 03Webhookイベントの冪等処理
- 04長時間のAI文書処理パイプライン
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill inngestインストール後、Claude Code で/inngestを入力して読み込まれたか確認します。
詳細
Inngest 統合
サーバーレス優先のバックグラウンドジョブ、イベント駆動型ワークフロー、キューやワーカーを管理せずに実現する耐久性のある実行に精通した Inngest エキスパートです。
これらはバージョン固定された SDK 向けのソーススケッチであり、デプロイ可能な完全なアプリケーションではありません。レビュー済みのデータベース/メール/決済アダプターを用意し、インストール済みの SDK に対してコンパイルしてください。イベントと Webhook ペイロードは、サーバー側で検証と認可を行う必要があります。Webhook イベントをキューに登録する前に、プロバイダーの署名を検証してください。秘密情報や不要な個人データを、耐久性のあるステップ出力に含めないでください。これらはリモートに保持される場合があります。
原則
- イベントが基本要素です。すべてはキューではなくイベントを起点にします
- ステップはチェックポイントです。各ステップの結果は耐久的に保存されます
- スリープはその場しのぎではありません。Inngest のスリープは実際のスリープであり、スレッドをブロックしません
- リトライは自動で行われますが、ポリシーは制御できます
- 関数は単なる HTTP ハンドラーです。HTTP を提供する場所ならどこにでもデプロイできます
- 同時実行は最優先事項です。下流サービスを保護してください
- ワークフローの重複排除によって、外部の副作用が厳密に一度だけ実行されるわけではありません。プロバイダーの冪等性キーを使用し、不確実な結果を照合してください
- ファンアウトは組み込み機能です。1 つのイベントで複数の関数を起動できます
機能
- inngest-functions
- event-driven-workflows
- step-functions
- serverless-background-jobs
- durable-sleep
- fan-out-patterns
- concurrency-control
- scheduled-functions
対象範囲
- redis-queues -> bullmq-specialist
- serverless-queues -> upstash-qstash
- workflow-orchestration -> temporal-craftsman
- message-streaming -> event-architect
- infrastructure -> infra-architect
ツール
コア
- inngest
- inngest-cli
フレームワーク
- nextjs
- express
- hono
- remix
- sveltekit
デプロイ
- vercel
- cloudflare-workers
- netlify
- railway
- fly-io
#メッセージ送信、課金、フルフィルメント、デプロイ、リモートインデックス作成などの副作用には、ユーザーのタスク範囲に含まれている必要があります。開発では合成レコードを使用し、レビュー中にこれらの例を実行しないでください。
パターン
- step-functions
- event-fan-out
- scheduled-cron
- webhook-handling
パターン
基本的な関数の設定
Next.js で型付きイベントを使用する Inngest 関数
使用する場面:任意の Next.js プロジェクトで Inngest を使い始めるとき
// lib/inngest/client.ts import { Inngest, EventSchemas } from 'inngest';
export const inngest = new Inngest({ id: 'my-app', schemas: new EventSchemas().fromRecord(), });
// イベントを型付きで定義する 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 }) => { // ステップ 1:ユーザーの詳細を取得する const user = await step.run('get-user', async () => { return await db.users.findUnique({ where: { id: event.data.userId } }); });
// ステップ 2:ウェルカムメールを送信する
await step.run('send-email', async () => {
await resend.emails.send({
to: user.email,
subject: 'Welcome!',
template: 'welcome',
});
});
// ステップ 3:24 時間待ってから、ヒントを送信する
await step.sleep('wait-for-tips', '24h');
await step.run('send-tips', async () => {
await resend.emails.send({
to: user.email,
subject: 'Getting Started Tips',
template: 'tips',
});
});
} );
// 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], });
マルチステップワークフロー
並列ステップとエラー処理を含む複雑なワークフロー
使用する場面:複数のサービスや長い待ち時間を伴う処理
export const processOrder = inngest.createFunction( { id: 'process-order', retries: 3, concurrency: { limit: 10 }, // 同時に処理する注文の最大数は10件 }, { event: 'order/placed' }, async ({ event, step }) => { const { orderId } = event.data;
// 並列ステップ — どちらも同時に実行されます
const [inventory, payment] = await Promise.all([
step.run('check-inventory', () => checkInventory(orderId)),
step.run('validate-payment', () => validatePayment(orderId)),
]);
if (!inventory.available) {
// 直接呼び出す代わりにイベントを送信します(ファンアウトパターン)
await step.sendEvent('notify-backorder', {
name: 'order/backordered',
data: { orderId, items: inventory.missing },
});
return { status: 'backordered' };
}
// サーバー側の注文から、正確な金額/通貨と顧客情報を取得します。
// 信頼できないイベントから受け取った金額だけを使って、決済してはいけません。
const order = await step.run('load-order', () => loadAuthorizedOrder(orderId));
// 決済を処理します
const charge = await step.run('charge-payment', async () => {
return await stripe.charges.create({
amount: order.totalMinorUnits,
currency: order.currency,
customer: payment.customerId,
}, { idempotencyKey: `order:${orderId}:charge:v1` });
});
// 注文を発送します
await step.run('ship-order', () => fulfillment.ship(orderId));
return { status: 'completed', chargeId: charge.id };
} );
スケジュール/Cron 関数
スケジュールに従って実行される関数
使用する場面:日次レポートやクリーンアップジョブなどの定期タスク
export const dailyDigest = inngest.createFunction( { id: 'daily-digest' }, { cron: '0 9 * * *' }, // 毎日午前9時(UTC) async ({ step }) => { // ダイジェストを希望するすべてのユーザーを取得します const users = await step.run('get-users', async () => { return await db.users.findMany({ where: { digestEnabled: true }, }); });
// 各ユーザーに送信します(子イベントを作成します)
await step.sendEvent(
'send-digests',
users.map(user => ({
name: 'digest/send',
data: { userId: user.id },
}))
);
return { sent: users.length };
} );
// 個別のダイジェスト送信は別の関数で処理します export const sendDigest = inngest.createFunction( { id: 'send-digest', concurrency: { limit: 50 } }, { event: 'digest/send' }, async ({ event, step }) => { // ... 個別のダイジェストを送信します } );
冪等性を備えた Webhook ハンドラー
重複を排除して Webhook を安全に処理します
使用する場面:Stripe、GitHub などの Webhook を処理する場合
export const handleStripeWebhook = inngest.createFunction( { id: 'stripe-webhook', // Stripe イベント ID で重複を排除します idempotency: 'event.data.stripeEventId', }, { event: 'stripe/webhook.received' }, async ({ event, step }) => { const { type, data } = event.data;
switch (type) {
case 'checkout.session.completed':
await step.run('fulfill-order', async () => {
await fulfillOrder(data.session.id);
});
break;
case 'customer.subscription.deleted':
await step.run('cancel-subscription', async () => {
await cancelSubscription(data.subscription.id);
});
break;
}
} );
長時間処理を伴う AI パイプライン
チャンク単位で処理する複数ステップの AI 処理
使用する場面:完了までに数分かかる可能性がある AI ワークフロー
export const processDocument = inngest.createFunction( { id: 'process-document', retries: 2, concurrency: { limit: 5 }, // API の使用を制限 }, { event: 'document/uploaded' }, async ({ event, step }) => { // ステップ 1:テキストを抽出(時間がかかる場合があります) const text = await step.run('extract-text', async () => { return await extractTextFromPDF(event.data.fileUrl); });
// ステップ 2:埋め込み用にチャンク化
const chunks = await step.run('chunk-text', async () => {
return chunkText(text, { maxTokens: 500 });
});
// ステップ 3:埋め込みを生成(API のレート制限あり)
const embeddings = await step.run('generate-embeddings', async () => {
return await openai.embeddings.create({
model: 'text-embedding-3-small',
input: chunks,
});
});
// ステップ 4:ベクトル DB に保存
await step.run('store-vectors', async () => {
await vectorDb.upsert({
vectors: embeddings.data.map((e, i) => ({
id: `${event.data.documentId}-${i}`,
values: e.embedding,
metadata: { chunk: chunks[i] },
})),
});
});
return { chunks: chunks.length, status: 'indexed' };
} );
検証チェック
Inngest の serve ハンドラーが存在する
重大度:重大
メッセージ:Inngest がイベントを受信するには、serve ハンドラーが必要です
修正方法:serve() をエクスポートする app/api/inngest/route.ts を作成します
serve に関数が登録されている
重大度:エラー
メッセージ:すべての Inngest 関数が serve() の呼び出しに登録されていることを確認してください
修正方法:serve() の functions 配列に関数を追加します
Step.run に説明的な名前が付いている
重大度:警告
メッセージ:ステップ名にはケバブケースを使い、内容が分かる名前を付けてください
修正方法:'fetch-user' や 'send-email' のような説明的なステップ名を使用します
waitForEvent にタイムアウトが設定されている
重大度:エラー
メッセージ:無期限の待機を防ぐため、waitForEvent にはタイムアウトを設定してください
修正方法:タイムアウトオプションを追加します:{ timeout: '24h' }
関数に同時実行数の上限がある
重大度:警告
メッセージ:下流サービスを保護するため、同時実行数の上限を設定することを検討してください
修正方法:関数の設定に concurrency: { limit: 10 } を追加します
イベント型が定義されている
重大度:警告
メッセージ:型安全性を確保するため、Inngest クライアントでイベントスキーマを定義してください
修正方法:schemas: new EventSchemas().fromRecord() を追加します
関数に一意の ID がある
重大度:重大
メッセージ:すべての Inngest 関数には一意の ID が必要です
修正方法:関数の設定に id: 'my-function-name' を追加します
Sleep に期間文字列を使用している
重大度:警告
メッセージ:step.sleep にはミリ秒ではなく、'1h' や '30m' のような期間文字列を使用してください
修正方法:期間文字列を使用します:step.sleep('wait', '1h')
再試行ポリシーが設定されている
重大度:警告
メッセージ:失敗への対処として、再試行ポリシーの設定を検討してください
修正方法:固定された SDK がサポートする retries オプションを設定してください。バックオフオブジェクトのスキーマを独自に作らないでください
支払い関数に冪等性キーがある
重大度:エラー
メッセージ:支払い関連の関数では、冪等性キーを使用してください
修正方法:ワークフローの重複排除とプロバイダー側の冪等性を、承認済みの注文に関連付けてください。ワークフローの設定だけでは、クラッシュ後の二重請求を防げません
コラボレーション
委譲のトリガー
- redis|queue infrastructure|bullmq -> bullmq-specialist(既存のインフラストラクチャを使用してRedisベースのキューが必要な場合)
- serverless queue|http queue|scheduled http -> upstash-qstash(イベントフレームワークを使わずに、プレーンなHTTP配信とcronが必要な場合)
- saga|compensation|rollback|long-running workflow -> temporal-craftsman(補償処理を伴う複雑なワークフローオーケストレーションが必要な場合)
- event sourcing|event store|cqrs -> event-architect(イベントソーシングのパターンが必要な場合)
- vercel|deploy|production -> vercel-deployment(デプロイ設定が必要な場合)
- database|schema|data model -> supabase-backend(イベントデータ用のデータベースが必要な場合)
- api|endpoint|route -> backend(イベントをトリガーするAPIが必要な場合)
Vercelのバックグラウンドジョブ
スキル:inngest、nextjs-app-router、vercel-deployment
ワークフロー:
1. Define Inngest functions (inngest)
2. Set up serve handler in Next.js (nextjs-app-router)
3. Configure function timeouts (vercel-deployment)
4. Deploy and test (vercel-deployment)
AIパイプライン
スキル:inngest、ai-agents-architect、supabase-backend
ワークフロー:
1. Design AI workflow steps (ai-agents-architect)
2. Implement with Inngest durability (inngest)
3. Store results in database (supabase-backend)
4. Handle retries for API failures (inngest)
Webhook処理
スキル:inngest、stripe-integration、backend
ワークフロー:
1. Receive webhook (backend)
2. Send to Inngest with idempotency (inngest)
3. Process payment logic (stripe-integration)
4. Update application state (backend)
メールの自動化
スキル:inngest、email-systems、supabase-backend
ワークフロー:
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)
スケジュールされたタスク
スキル:inngest、backend、analytics-architecture
ワークフロー:
1. Define cron triggers (inngest)
2. Implement processing logic (backend)
3. Aggregate and report data (analytics-architecture)
4. Handle failures with alerting (inngest)
関連スキル
相性の良いスキル:nextjs-app-router、vercel-deployment、supabase-backend、email-systems、ai-agents-architect、stripe-integration
使用する場面
- ユーザーがinngestについて言及している、または示唆している
- ユーザーがサーバーレスのバックグラウンドジョブについて言及している、または示唆している
- ユーザーがイベント駆動型ワークフローについて言及している、または示唆している
- ユーザーがステップ関数について言及している、または示唆している
- ユーザーが耐久性のある実行について言及している、または示唆している
- ユーザーがvercelのバックグラウンドジョブについて言及している、または示唆している
- ユーザーがスケジュールされた関数について言及している、または示唆している
- ユーザーがファンアウトについて言及している、または示唆している
制限事項
- 上記で説明されている範囲にタスクが明確に該当する場合にのみ、このスキルを使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認してください。