Supabase Edge Function 冷启动慢:3 个原因 + 修复路径

第一次请求 2–5 秒——Deno isolate 没暖、依赖太大、外部 API 加成。

你部署了一个 Supabase Edge Function,本地用 supabase functions serve 跑稳定 ~100ms。生产环境第一次请求 2-5 秒,后面再请求又恢复 100-200ms——半小时不用又慢回去。这是典型的冷启动现象,几乎所有 serverless 平台都有,但 Supabase Edge Functions(基于 Deno isolate)的冷启动模式有自己的特点。

理解关键:Supabase Edge Function 长时间没流量会被 evict(Deno isolate 释放掉)。下次请求要重新 spawn isolate、加载代码、import 依赖、跑模块顶层初始化——这几步加起来就是你看到的 2-5 秒。

常见原因

按命中率从高到低:

1. Function 长时间无请求被休眠

Supabase Edge Functions 空闲 ~5-15 分钟会 evict。下次请求触发完整 cold start。

如何判断:用户报”凌晨 / 周末偶尔很慢”——典型的低流量时段冷启动。

2. import 了大依赖(特别是 npm 包)

import { Anthropic } from 'npm:@anthropic-ai/sdk';  // ~500KB
import { OpenAI } from 'npm:openai';                // ~1MB
import _ from 'npm:lodash';                          // ~70KB

Deno 第一次跑要下载 + transpile 这些包,慢启动直接 +1-3 秒。

如何判断:function 顶部有多个 npm: import。

3. 模块顶层做了重活

// ❌ 顶层跑——每次 cold start 都执行
const config = await fetch('https://...').then(r => r.json());
const dbConnection = await connectDB();

Deno.serve(async (req) => { ... });

每次 isolate 启动这些都重跑,叠加在 cold start 上。

如何判断:function 顶部有 await 或长同步计算。

4. cold start 时打外部 API

Deno.serve(async (req) => {
  // ❌ cold start 时这个 fetch 也算冷
  const data = await fetch('https://slow-third-party.com/data');
  ...
});

upstream 自己慢 → 你 cold start + upstream slow 都摊到 first request。

如何判断:function 里第一个 await 调用是外部 API。

5. 包含大 JSON / WASM blob

在 function 顶部 import 一个 5MB 的 JSON 数据集或 WASM 模块,parse / instantiate 都耗时。

如何判断:repo 里 functions 目录下有大 .json / .wasm 文件。

6. 区域不匹配(用户在 Asia、function 在 US)

cold start 本身慢 + 跨地区网络延迟,体感 5+ 秒。

如何判断:Supabase Dashboard → Settings → Project → Region 跟主要用户区域不一致。

最短修复路径

Step 1:测量真实 cold start

# 等待 15 分钟无请求
# 然后第一次请求计时
time curl -X POST "https://xyz.supabase.co/functions/v1/my-fn" \
  -H "Authorization: Bearer $KEY"

# 比对后续请求(warm)
time curl -X POST "..."

记录 cold vs warm 差值——这就是 cold start 真实代价。

Step 2:cron 保温(最简单粗暴)

如果可以接受额外 invocations:

-- Supabase Dashboard → Database → Cron
SELECT cron.schedule(
  'keep-warm',
  '*/5 * * * *',  -- 每 5 分钟
  $$ SELECT net.http_post(
    url := 'https://xyz.supabase.co/functions/v1/my-fn',
    headers := '{"Authorization": "Bearer ANON_KEY"}'::jsonb,
    body := '{"warmup": true}'::jsonb
  ); $$
);

function 里识别 warmup 请求快速返回:

if (body.warmup) return new Response('ok');

成本:每月 ~8640 次额外 invocations(5 分钟一次),Supabase 免费档够。

Step 3:依赖瘦身

// ❌ 全 SDK
import Anthropic from 'npm:@anthropic-ai/sdk';

// ✅ 自己写 fetch(节省 import 时间)
async function callAnthropic(messages: any[]) {
  return fetch('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: {
      'x-api-key': Deno.env.get('ANTHROPIC_API_KEY')!,
      'anthropic-version': '2023-06-01',
    },
    body: JSON.stringify({ model: 'claude-opus-4-7', messages }),
  });
}

每个 SDK 替换为原生 fetch 可省 1-2 秒。

Step 4:把顶层初始化挪到 handler 里

// ❌ 顶层
const config = await loadConfig();
Deno.serve(async (req) => { ... });

// ✅ handler 里 lazy load + cache
let configPromise: Promise<Config> | null = null;
Deno.serve(async (req) => {
  configPromise ??= loadConfig();  // 只在第一次请求时 load
  const config = await configPromise;
  ...
});

warm 状态下 configPromise 已经 resolve,不重复 load。

Step 5:外部 API 异步化

Deno.serve(async (req) => {
  const result = await quickProcess(req);

  // 慢的外部 API 不阻塞响应
  // 用 EdgeRuntime.waitUntil 让 Supabase 在响应后继续执行
  // @ts-expect-error EdgeRuntime is a Supabase global
  EdgeRuntime.waitUntil(slowExternalCall());

  return Response.json(result);
});

Step 6:换平台 / 区域

如果冷启动对你业务关键、或者你流量分散在全球:

低冷启动场景:
- Cloudflare Workers(V8 isolate,cold start ~5ms)
- Vercel Edge Functions(类似)
- 永远 warm 的 Node serverless(Fly.io Machine、Railway)

只需修复 Supabase region:
- Dashboard → Project → Settings → Region
  → 选最近用户的 region

注意 region 一旦改不容易回退,先评估再改。

预防建议

  • 设计时就估算冷启动可接受度:如果是后台同步任务可以慢,用户实时交互必须 < 500ms
  • 对延迟敏感的 endpoint 用 cron 保温(小项目)或换 Cloudflare Workers(大流量)
  • function 顶层零异步 import / 零 fetch / 零长计算,只声明
  • 依赖能不引则不引;能用原生 fetch 替代就用
  • 大 JSON 数据放 Supabase Storage / 外部 KV,按需读取
  • 监控 p99 latency 区分 cold vs warm,alert 高 cold start 比例
  • 用户主要在 Asia / EU 就选对应 region,跨大洲冷启动叠加网络延迟会爆

相关阅读

标签: #独立开发 #排查 #排查