Firebase 配额超限:3 个原因 + 修复路径

Firestore 写入 / Functions 调用 / Hosting 带宽——免费档每项都有红线。

你 Firebase 项目突然全线挂了:Firestore 读不到数据、Functions 全部 503、Hosting 返回 quota error——但你没改任何代码。Console 红色横幅写着 “Quota exceeded for quota metric …”。这是 Firebase Spark(免费)计划的硬上限触发,或 Blaze 计划碰到某个 per-day quota。问题不在于”配额满了”,而在于你没设过任何告警,所以满了你才知道

理解关键:Firebase 不是单一额度,而是几十个 metric 分别计费(Firestore reads / writes / deletes / storage GB / Functions invocations / GB-seconds / Hosting bandwidth / Auth verifications…)。任一项打到 cap 就 503。

常见原因

按命中率从高到低:

1. Spark 免费计划某项打到硬上限

Spark 是硬封顶(不能透支),常见红线:

Firestore reads:       50K / day
Firestore writes:      20K / day
Firestore deletes:     20K / day
Firestore storage:     1 GB
Functions invocations: 125K / month
Hosting bandwidth:     10 GB / month
Auth verifications:    unlimited (但 phone auth 是 100 / day)

如何判断Firebase Console → Usage and billing → 看哪一项 100%。

2. Functions 死循环烧调用数

常见反模式:

// 写 Firestore 触发 onWrite → 又写 Firestore → 又触发 onWrite → ...
exports.onUserUpdate = onDocumentWritten('users/{uid}', async (event) => {
  await db.doc(`users/${event.params.uid}`).update({...}); // ❌ 会触发自身
});

24 小时能烧完 1 个月免费额度。

如何判断:Console → Functions → 看单个函数的 invocations 异常高(百万级)。

3. 客户端死循环读 Firestore

function Comp() {
  useEffect(() => {
    onSnapshot(query, snap => {
      setItems(snap.docs);  // 触发 re-render → 又 useEffect → 又 subscribe
    });
  }); // ❌ 缺 deps array
}

10 个活跃用户能让你免费额度 1 小时清零。

如何判断:Console → Firestore → Usage → reads/sec 不正常地高。

4. 大文件 / 视频 hosting 带宽爆

把 100MB 视频放 Firebase Hosting,1000 个用户看 = 100GB,超 10GB 免费额度 10 倍。

如何判断:Hosting bandwidth 异常高,对照你的访问量。

5. 没设 Firestore TTL,老数据堆积

Firestore 存的 logs / sessions / analytics 没清理,几个月就把 1GB 撑爆。

如何判断:Storage 超 1GB 但你没那么多用户数据。

6. 恶意爬虫 / 攻击者扫数据

你的客户端 SDK 调 Firestore 没充分 security rules,攻击者发现 endpoint 后能直接 query 任意数据,bandwidth 和 reads 双爆。

如何判断:用户量没变但 reads 突增 100x。

最短修复路径

Step 1:定位哪一项爆了

Firebase Console → Usage and billing
  → 看 Firestore / Functions / Hosting / Auth 各项
  → 100% 红色那项就是元凶

不要凭感觉猜,看仪表盘。

Step 2:紧急止血——升 Blaze + 设硬上限

如果你需要立刻恢复,升 Blaze(按用量付费)但同时设 Budget Cap 和 Alert

1. GCP Console → Billing → Budgets & alerts → Create budget
2. Budget amount: $20(你愿意承受的最大月支出)
3. Alert thresholds: 50%, 90%, 100%
4. Alert recipients: 你的 email
5. 重要:勾选 "Disable billing" actions 防止失控

注意:Blaze 不能真的”硬封顶”消费——这只是 alert + auto-disable,已发生的费用还是要付。

Step 3:定位异常源

异常源 = 用户脚本 / 死循环 / 攻击者

如果是 Functions 死循环:
  立刻去 Console → Functions → 找异常那个 → Disable

如果是客户端死循环:
  立刻回滚最新前端版本
  或 hotfix 前端 useEffect 加 deps

如果是攻击者:
  立刻临时把 Firestore rules 改紧(match /{document=**} { allow read, write: if false; })
  然后慢慢恢复合理 rules

Step 4:把 Functions 加防呆

// 防止自己触发自己
exports.onUserUpdate = onDocumentWritten('users/{uid}', async (event) => {
  // 如果是 _serverUpdate flag 触发的,跳过避免循环
  const after = event.data?.after.data();
  if (after?._serverUpdate) return;

  await db.doc(`users/${event.params.uid}`).update({
    derived: ...,
    _serverUpdate: true,  // mark
  });
});

或更彻底——分两个 collection 隔离写入。

Step 5:客户端 useEffect 加 deps

useEffect(() => {
  const unsub = onSnapshot(query, snap => setItems(snap.docs));
  return () => unsub();
}, []);  // ✅ empty deps

Step 6:紧 Firestore security rules

最小权限:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read, write: if request.auth.uid == uid;
    }
    match /posts/{post} {
      allow read: if true;
      allow write: if request.auth != null
                   && request.resource.data.authorId == request.auth.uid;
    }
  }
}

部署:firebase deploy --only firestore:rules

Step 7:减少不必要 reads

// 慢:每次都全量 query
const all = await getDocs(collection(db, 'posts'));

// 快:分页 + cache
const first = await getDocs(query(
  collection(db, 'posts'),
  orderBy('createdAt', 'desc'),
  limit(20)
));

// 客户端 React 用 SWR / TanStack Query 缓存,避免重复 fetch

预防建议

  • 所有项目上线先在 GCP Billing 设 Budget Alert 50% / 90% / 100%,邮件通知
  • Firestore security rules 写紧——默认 deny all,按需 allow
  • Functions 永远不要订阅自己写的 collection;如必须,用 flag 防循环
  • 客户端 useEffect 一定有 deps array;用 lint 规则强制
  • 大文件不要 Firebase Hosting,用 R2 / S3 + CDN
  • 老数据加 Firestore TTL policy 自动清理(log / session / analytics)
  • 监控 reads/sec / writes/sec,异常 spike 立刻 alert
  • 项目用前估算月成本:(daily reads × 30 × $0.06/100K) + … 心里有数

相关阅读

标签: #Firebase #排查 #排查