Fluid Compute が無効でも関数インスタンスの再利用は起こる
この記事の内容
Vercel の Fluid Compute を有効にするとリクエスト間で関数インスタンスを共有することになります。
それによって、たとえばグローバル変数が共有されるようになるので、今まで起こり得なかった漏洩が起こるようになるのではないか? という説を耳にしました。
そこで、そもそも従来のサーバーレス関数ならグローバル変数は共有されないのか? という点を検証しました。
実際に試したこと
環境
- Next.js 15.3.3
- デプロイ先は Vercel の Hobby Plan
実装
下記のような Route Handler を作りました。
const data: number[] = [];
export async function GET() {
data.push(Math.random());
await sleep(3000);
return Response.json({
data
});
}
async function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
早速、検証のために作った関数を Vercel にデプロイします。
新しく Vercel でプロジェクトを作ると Fluid Compute が ON になっているので、しっかり OFF にしてからデプロイしなおしましょう。
検証結果
従来のサーバーレス関数でリクエストごとに別々の関数インスタンスが起動しているとしたら、グローバル変数 data
はリクエストごとに毎回初期化され、レスポンスで返ってくる配列の中身は常に一つだけになりそうです。
実際には、Fluid Compute が OFF の状態の /api/test
へ連続してアクセスした結果は下記のようになりました。
{
"data": [0.680118147128416, 0.340835684160808]
}
data
の中身は前のリクエストの中身を引き継いで増えていきました。
結論
検証結果から、従来のサーバーレス関数について「リクエストごとに別々の関数インスタンスが作られ、リクエスト完了後即座に破棄される」という理解は正確ではないと思います。
公式ドキュメントがもう Fluid Compute 前提の記述になっているので、この挙動についての記載が見つけられなかったのですが、おそらく AWS Lambda と同様の関数インスタンスの再利用があるのだと考えられます。
Q: AWS Lambda は関数インスタンスを再利用しますか?
パフォーマンス向上のため、AWS Lambda は新しく関数のインスタンスを作成するのではなく、関数のインスタンスを保持してその後のリクエストに対応することがあります。Lambda で関数インスタンスを再利用する方法の詳細については、「ドキュメント」を参照してください。ただし、常にインスタンスを再利用するわけではありません。
Fluid Compute を有効にしているかどうかによらず、他のリクエストとの間でグローバルなリソースが共有されると困るような実装はしないようにしましょう。
Discussion