Vercel Edge FunctionsでLLM APIを扱うときにハマった制約まとめ
はじめに
AI診断系のSaaSを個人開発する中で、Vercel Edge Functions + LLM APIという構成を採用しました。
結論から言うと、
Edgeは速い。でも万能ではない
この記事では、実際にEdge FunctionsでLLM APIを扱ってハマった制約とどう設計で回避したかをまとめます。
なぜEdge Functionsを使ったか
今回の要件は以下です。
- レスポンスはできるだけ速くしたい
- DBを使わないステートレスAPI
- 小規模・個人開発
- トラフィックはそこまで多くない
この条件だと、
- Goサーバー → 過剰
- Node Serverless → 十分だが起動コストあり
- Edge Functions → 起動0ms・実装簡単
という理由でEdgeを選びました。
Edge Functionsの基本的な特徴
良いところ
- コールドスタートほぼゼロ
- 地理的にユーザーに近い
- Next.js Route Handlersと相性が良い
ただし…
制約がかなり多い
ここからが本題です。
制約①:Node.js APIが使えない
Edge FunctionsはWeb標準APIのみです。
使えない代表例
fscrypto(Node版)- 一部のSDK(OpenAI SDKの古いものなど)
対策
- fetchベースのSDKを使う
- もしくはREST APIを直接叩く
typescript
const res = await fetch("<https://api.openai.com/v1/chat/completions>", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages,
}),
});
👉 Edgeでは**「SDKが使えるか」を必ず事前確認する**
制約②:実行時間が短い(LLMは遅い)
Edge Functionsは基本的に
- 数秒レベルの実行を想定
- 長時間処理に向かない
問題
- プロンプトが長い
- LLMの応答が遅い
- 再試行ロジックを入れると詰む
設計上の工夫
- 1リクエスト = 1推論
- 再生成はフロント主導
- 失敗時は即エラーを返す
typescript
if (!res.ok) {
return new Response("LLM error", { status: 500 });
}
👉 Edgeでは**「粘らない設計」が重要**
制約③:レスポンスサイズ制限
LLMの出力が長くなると、Edgeのレスポンス制限に引っかかる可能性があります。
対策
- 出力は構造化JSON
- 無駄な自然文を出させない
- UI側で文章を組み立てる
json
{
"persona": "Explorer",
"strengths": ["curiosity", "speed"],
"weaknesses": ["lack of focus"]
}
👉 LLMにUI文章を全部書かせない
制約④:環境変数の扱いに注意
Edgeでもprocess.envは使えますが、
- ビルド時に埋め込まれる
- ローカルと本番で挙動差が出やすい
実践ルール
- Edge用APIキーは最小権限
.env.localとVercel Envを必ず同期
Node Serverlessとの使い分け
| 処理 | Edge | Node |
|---|---|---|
| 軽い診断 | ◎ | ○ |
| 長文生成 | △ | ◎ |
| 再試行ロジック | × | ◎ |
| DB操作 | △ | ◎ |
今回の判断
- 診断API:Edge
- 将来の重い処理:Node or Go
👉 「最初から全部Edge」はやらない
結論:Edgeは"速さ特化の刃物"
- Edge Functionsは強力
- でも制約前提で設計しないと詰む
- LLM用途では特に注意が必要
向いているケース
- 単発・軽量なAI推論
- ステートレスAPI
- UX重視のプロダクト
向いていないケース
- 長時間処理
- 複雑なリトライ
- 重いSDK依存
おわりに
今回のAI診断SaaSでは、
Edgeで速さを取り、設計で制約を受け流す
という判断が結果的にうまくいきました。
これからEdge × LLMを使う人の「最初の地雷回避」になれば嬉しいです。