Vercel2026-06-25
【インフラ】タイムアウト知らずの非同期処理:Vercel Workflowsを用いた長時間バッチ処理の実装パターン
サーバーレスが抱える「実行時間」の壁
サーバーレスアーキテクチャ(Vercel FunctionsやAWS Lambdaなど)は、高い拡張性とミリ秒単位の課金体系という絶大なメリットを持つ一方、**「短時間の処理しか行えない」**という大きな設計上の制約があります。
例えば、Vercelの通常プランでは以下の制限があります。
- Hobby(無料)プラン: APIのタイムアウト最大 10秒
- Proプラン: APIのタイムアウト最大 60秒(設定により最大30分まで延長可能)
この制限は、以下のような「重い」B2B処理を実行する際の大きな壁になります。
- 大規模データのマイグレーション: 数万件の顧客レコードを別のDBに転記する。
- AIによるバッチ要約: 数百件のドキュメントを順次読み込み、要約してPDFを作成する。
- 外部APIとの逐次同期: 相手先システムの接続制限に配慮しながら、ゆっくりデータをポーリングする。
これらを通常のAPIで実行すると、処理の途中でタイムアウトが発生し、データが不完全な状態で停止してしまいます。この「実行時間の制限」を根本的にクリアするのが、Vercel Workflows によるステップ実行とステート管理です。
2. 課題解決のビフォー・アフター
| 項目 | 従来のサーバーレス関数(Before) | Vercel Workflows(After) |
|---|---|---|
| 許容実行時間 | 10秒〜数分で強制シャットダウン | 各ステップに分割することで、数時間〜数日間のワークフローを実行可能 |
| リトライ制御 | エラー発生時、最初から全てやり直し | エラーが発生したステップのみを自動再試行(バックオフ) |
| 一時待機(Sleep) | 待機中もサーバー起動費用が発生 | context.sleepにより、実行を一時サスペンド(課金ゼロ) |
| 進捗状況の可視化 | バックグラウンドで何が起きているか不明 | 管理画面からどのステップが完了したかがリアルタイムに視認可能 |
3. 具体的な実装例:ステップに分割されたデータ移行バッチ
大量のデータを小分けにして順次移行し、失敗時は自動リトライするワークフローのTypeScript実装例です。
import { workflow } from "@vercel/workflows";
export const dataMigrationWorkflow = workflow(async (context) => {
// 移行対象のアイテムIDリストを取得(Step 1)
const itemIds = await context.run("fetch-target-items", async () => {
const response = await fetch("https://api.source-db.com/items");
const data = await response.json();
return data.ids as string[];
});
const batchSize = 50;
// アイテムリストを50個ずつのバッチに分割して順次処理
for (let i = 0; i < itemIds.length; i += batchSize) {
const chunk = itemIds.slice(i, i + batchSize);
const chunkIndex = Math.floor(i / batchSize);
// 各バッチの処理を独立したステップとして実行(Step 2〜N)
await context.run(`process-batch-${chunkIndex}`, async () => {
const response = await fetch("https://api.destination-db.com/batch-import", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ids: chunk }),
});
if (!response.ok) {
// ここでスローされたエラーは、Vercel Workflowsの設定に基づき自動リトライされます
throw new Error(`Batch ${chunkIndex} failed with status: ${response.status}`);
}
});
// 移行先APIのレートリミットを考慮し、バッチごとに10秒間待機(待機時間は課金対象外)
await context.sleep(`sleep-after-batch-${chunkIndex}`, 10);
}
// 移行完了後にシステム管理者へ通知(Final Step)
await context.run("notify-admin", async () => {
await sendSlackNotification(`🎉 合計 ${itemIds.length} 件のデータ移行ワークフローが正常に完了しました。`);
});
});
async function sendSlackNotification(message: string) {
await fetch(process.env.SLACK_WEBHOOK_URL!, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: message }),
});
}
4. HadayaLabの長時間処理バックエンド構築
HadayaLabでは、中堅企業様の「業務の自動化(BPR)」を進める上で発生する、サーバーレス環境での長時間バッチや耐障害性の高いバックエンド開発を得意としています。
- Vercel Workflowsの設計導入: 既存の重い処理を調査し、最適なワークフローステップに分解。
- 耐障害性の高い外部API接続: Webhookの消失防止や、レート制限を回避するためのキュー(Queue)設計。
- 状態監視ダッシュボードの構築: 実行中の自動化タスクが正常に進んでいるか、ダッシュボードから一目で追跡できる可視化支援。
「既存のバッチ処理がエラーでよく途切れてしまう」「APIの制限で自動化が難航している」とお悩みのITリーダーの方は、ぜひHadayaLabのサーバーレスインフラ構築支援をご利用ください。