inngest-v3-v4-migration について
inngest-v3-v4-migrationは、既存のInngestコードベースをv3からv4へ移行するエージェントスキルです。使用状況の調査からAPI更新、型チェック、対象を絞ったテストまで、段階的な移行を案内します。
主な機能
- 01Inngestの利用状況とSDKバージョンの調査
- 02破壊的なAPI変更の順次適用
- 03トリガーとイベントスキーマの移行
- 04realtimeとstep.invokeの更新
- 05型チェックと対象を絞ったテストによる検証
活用シーン
- 01プロジェクトのInngest v3からv4への更新
- 02v3とv4のAPIが混在するコードの修正
- 03移行に伴う型エラーの解決
- 04移行後の実行時動作の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ inngest/ inngest-skills --skill inngest-v3-v4-migrationインストール後、Claude Code で/inngest-v3-v4-migrationを入力して読み込まれたか確認します。
詳細
Inngest v3 から v4 への移行
ユーザーが Inngest のアップグレード、v3/v4 のエラー修正、リアルタイムの移行、または SDK パターンが混在したコードベースの整理を依頼したときに、このスキルを使用します。
主な参照先: https://www.inngest.com/docs/reference/typescript/v4/migrations/v3-to-v4
このスキルはエージェントファーストです。まず実際の使用状況を検出し、制御された順序で機械的な API 変更を加え、その後で型チェックと対象を絞ったテストを実行します。
トリガーする条件
次のようなリクエストにこのスキルを使用します:
- 「Inngest を v3 から v4 にアップグレードする」
- 「Inngest v4 への移行を修正する」
- 「アップグレード後に signing key required / cloud mode エラーが発生する」
- 「文字列の関数 ID を指定した
step.invokeが動かなくなった」 - 「
inngest@4をインストールしたら@inngest/realtimeが壊れた」 - 「EventSchemas から eventType に移行する」
- 「この既存の Inngest リポジトリを v4 互換にする」
ユーザーがまずコードベース全体の信頼性監査を求めている場合は、inngest-brownfield-audit を使用して範囲を決め、その後で v4 の変更のためにここに戻ってください。
移行スキャン
まずすべての Inngest の利用箇所を特定します:
rg -n '"inngest"|"@inngest/realtime"|"@inngest/agent-kit"' package.json **/package.json
rg -n 'new Inngest|EventSchemas|eventType|staticSchema|createFunction\\(|serve\\(|connect\\(|step\\.invoke|referenceFunction|@inngest/realtime|realtimeMiddleware|useInngestSubscription|serveHost|rewriteGatewayEndpoint|logLevel|streaming:|signingKey|signingKeyFallback|baseUrl|INNGEST_DEV|INNGEST_SIGNING_KEY' .
次にリポジトリを分類します:
- まだ Inngest がない: この移行スキルではなく
inngest-setupを使用します。 - v3 のみ: SDK とすべての破壊的変更をまとめて移行します。
- v3/v4 混在: v4 コードから壊れた v3 API を削除することを優先します。
- v4 がほぼ完了: ローカル開発モード、サーバーレスの
maxRuntime、リアルタイムパッケージのインポート、文字列のstep.invokeなど、見落としがちな実行時の注意点に集中します。
編集する前に、次のことを記録します:
Inngest migration scan:
- Current package versions:
- Client files:
- Serve/connect entrypoints:
- Functions using old trigger syntax:
- EventSchemas usage:
- Realtime v3 package usage:
- step.invoke string IDs:
- Serverless runtime constraints:
- Tests/checks available:
アップグレードの順序
- パッケージのバージョンを更新します。
- クライアントの構築とローカル/本番モードを修正します。
- serve オプションをクライアントに移動します。
- トリガーを
createFunctionのオプションに移動します。 EventSchemasをeventType()/staticSchema()に置き換えます。step.invoke()の文字列 ID を書き換えます。- リアルタイムを
@inngest/realtimeから v4 ネイティブ API に移行します。 - ミドルウェアとログを更新します。
- チェックポイント処理/サーバーレスランタイムを設定します。
- 型チェックとテストを実行し、必要に応じて dev サーバーと同期します。
パッケージと環境
最新の v4 SDK をインストールします:
npm install inngest@latest
# or pnpm add inngest@latest
# or yarn add inngest@latest
リポジトリで v3 のリアルタイムを使用している場合は、@inngest/realtime を削除します。v4 のリアルタイムは inngest パッケージと、inngest/realtime、inngest/react などのサブパス、およびネイティブの step.realtime / inngest.realtime にあります。
v4 はデフォルトで Cloud モードになります。ローカル開発では環境変数を使用します:
INNGEST_DEV=1 npm run dev
リポジトリの既存の環境パターンが明確にローカル専用コードに限定している場合を除き、ソース内で isDev: true をハードコードしないでください。本番では INNGEST_SIGNING_KEY を使用する必要があります。
クライアントと serve オプション
v4 では、signingKey、signingKeyFallback、baseUrl などのオプションは serve(...) ではなく new Inngest(...) に指定します。
// Old v3
app.use(
"/api/inngest",
serve({
client: inngest,
functions,
signingKey: process.env.INNGEST_SIGNING_KEY,
baseUrl: process.env.INNGEST_BASE_URL,
})
);
// New v4
export const inngest = new Inngest({
id: "my-app",
signingKey: process.env.INNGEST_SIGNING_KEY,
baseUrl: process.env.INNGEST_BASE_URL,
});
app.use("/api/inngest", serve({ client: inngest, functions }));
リポジトリがすでにサポートされている環境変数に依存しており、serve オプションを明示的に渡していない場合、これらのキーについてはコード変更が不要なことがあります。
その他の名前の変更:
serveHost->serveOriginstreaming: "force"->streaming: truestreaming: "allow"->streaming: truestreaming: falseはfalseのままlogLevelは削除されました。new ConsoleLogger({ level })などのloggerを渡します
createFunction のトリガー
トリガーは第 1 引数のオプションオブジェクトに移動します。
// Old v3
inngest.createFunction(
{ id: "send-welcome" },
{ event: "user/created" },
async ({ event, step }) => {}
);
// New v4
inngest.createFunction(
{ id: "send-welcome", triggers: [{ event: "user/created" }] },
async ({ event, step }) => {}
);
Cron トリガーも同様に移動します:
inngest.createFunction(
{ id: "nightly-sync", triggers: [{ cron: "0 2 * * *" }] },
async ({ step }) => {}
);
関数が step.invoke 経由でのみ呼び出される場合は、トリガーなしでもかまいません。
EventSchemas から eventType/staticSchema へ
集中管理された EventSchemas を、イベントごとの定義に置き換えます。
import { Inngest, eventType, staticSchema } from "inngest";
import { z } from "zod";
export const userCreated = eventType("user/created", {
schema: z.object({
userId: z.string(),
email: z.string().email(),
}),
});
type InvoicePaid = {
invoiceId: string;
customerId: string;
};
export const invoicePaid = eventType("billing/invoice.paid", {
schema: staticSchema<InvoicePaid>(),
});
イベント型を一貫して使用します:
await inngest.send(userCreated.create({ userId, email }));
inngest.createFunction(
{ id: "on-user-created", triggers: [userCreated] },
async ({ event }) => {}
);
await step.waitForEvent("wait-for-invoice", {
event: invoicePaid,
timeout: "7d",
});
重要: staticSchema は interface ではなく type を想定しています。必要に応じて interface を型エイリアスに変換してください。
step.invoke
v4 では生の文字列の関数 ID を受け付けなくなりました。インポートした関数参照または referenceFunction() を使用します。
import { referenceFunction } from "inngest";
await step.invoke("run-report", {
function: referenceFunction({
appId: "analytics-app",
functionId: "generate-report",
}),
data: { reportId },
});
対象の関数が同じコードベースにある場合は、インポートした関数自体を渡すことを推奨します:
await step.invoke("run-report", {
function: generateReport,
data: { reportId },
});
リアルタイムの移行
v3 のリアルタイムは @inngest/realtime とミドルウェアで注入される publish を使用していました。
v4 のリアルタイムはネイティブです。
以下を置き換えます。
@inngest/realtimeパッケージrealtimeMiddleware(){ publish }などのハンドラー引数useInngestSubscription()などの v3 React フック
以下に置き換えます。
inngest/realtimeのチャネル定義- ステップ間の
step.realtime.publish - 既存の
step.run内でのinngest.realtime.publish - 現在の v4 API のサブスクリプションヘルパー/フック
詳細なパターンについては inngest-realtime を使用してください。
step.run の内部から step.realtime.publish を呼び出さないでください。ステップ内でステップが実行される動作を避けるには、そこで inngest.realtime.publish を使用してください。
並列性とチェックポイント
v4 では、最適化された並列性とチェックポイントがデフォルトで有効になっています。
ステップに対する Promise.race に注意してください。最適化された並列性では、Promise.race はすべてのステップの Promise が確定するまで待機します。リポジトリが最初に完了したものだけを採用する動作に依存している場合は、group.parallel() を使用してください。
サーバーレスプラットフォームでは、チェックポイントの maxRuntime をプラットフォームの制限より少し低く設定してください。
export const inngest = new Inngest({
id: "my-app",
checkpointing: {
maxRuntime: "50s",
},
});
Vercel などのフレームワークでは、プラットフォームが対応している場合はルートハンドラーの最大実行時間も設定してください。
Connect の変更
リポジトリが Connect を使用している場合:
rewriteGatewayEndpointはgatewayUrlに置き換えられます。- Connect はワーカースレッド分離を使用する場合があります。統合の問題が発生する場合は、
isolateExecution: falseまたはINNGEST_CONNECT_ISOLATE_EXECUTION=falseを確認してください。 - ターゲット URL と署名/イベントキーは環境変数に保持してください。
検証
信頼度を高めながら順にチェックを実行します。
- パッケージマネージャーでのインストール/更新。
- 型チェック。
- 移行した関数を対象とした単体/統合テスト。
INNGEST_DEV=1を指定してアプリを起動。npx inngest-cli@latest devを実行し、関数の検出を確認。- 代表的なイベントを 1 つ送信し、実行を検査。
ローカルの開発サーバーでの検証が不可能な場合は、どの静的チェックが成功し、どの実行時検証が残っているかを正確に記載してください。
よくある失敗メッセージ
- 「A signing key is required to run in Cloud mode」: ローカル開発では
INNGEST_DEV=1を設定するか、本番環境ではINNGEST_SIGNING_KEYを設定してください。 /api/inngestでのCls is not a constructor: v4 アプリに v3 の@inngest/realtimeミドルウェアが残っている可能性があります。パッケージを削除し、ネイティブのリアルタイムに移行してください。step.invokeが文字列の関数 ID で失敗する: 文字列を、インポートした関数参照またはreferenceFunction()に置き換えてください。- スキーマに関する型エラー:
EventSchemasをeventType()とstaticSchema()に置き換えてください。 - 予期しない
Promise.raceの動作: 最初に完了したステップを採用するレースにはgroup.parallel()を使用するか、必要な場合にのみ最適化された並列性を無効にしてください。
アンチパターン
- v3 のリアルタイムミドルウェアと
inngest@4を混在させる。 serve()にsigningKey、baseUrl、またはsigningKeyFallbackを渡す。- イベントトリガーの構文を移行したが、cron/invoke でトリガーされる関数を忘れる。
EventSchemasを型付けされていない文字列イベントにすべて置き換える。- 本番向けのソースに
isDev: trueをハードコードする。 step.invokeに文字列 ID を残す。- 機械的な移行後に型チェックを省略する。