Fix: Quota exceeded for quota metric Read requests in Firestore
The error RESOURCE_EXHAUSTED: Quota exceeded for quota metric 'Read requests' and limit 'Read requests per day' of service 'firestore.googleapis.com' indicates your application exhausted the complimentary 50,000 daily document reads granted by the Firebase Spark plan. All subsequent read operations fail until quota refresh.
Quick Diagnostics
limit() / startAfter() and enable local cache persistenceThe error RESOURCE_EXHAUSTED: Quota exceeded for quota metric 'Read requests' and limit 'Read requests per day' of service 'firestore.googleapis.com' indicates your application exhausted the complimentary 50,000 daily document reads granted by the Firebase Spark plan. All subsequent read operations fail until quota refresh.
Step-by-Step Solution
-
1
Step 1: Enable Multi-Tab Local Cache Persistence
Eliminate redundant network reads on page refresh by enabling offline disk persistence:
JAVASCRIPTimport { initializeFirestore, persistentLocalCache, persistentMultipleTabManager } from "firebase/firestore"; // Initialize Firestore with robust local storage caching const db = initializeFirestore(app, { localCache: persistentLocalCache({ tabManager: persistentMultipleTabManager() }) }); -
2
Step 2: Enforce Cursor-Based Pagination
Never fetch entire collections in a single round-trip. Segment results into discrete chunks:
JAVASCRIPTimport { collection, query, orderBy, startAfter, limit, getDocs } from "firebase/firestore"; // Efficient cursor-based pagination async function fetchPage(lastVisibleDoc = null) { let q = query( collection(db, "posts"), orderBy("createdAt", "desc"), limit(15) ); if (lastVisibleDoc) { q = query(q, startAfter(lastVisibleDoc)); } const snapshot = await getDocs(q); const items = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); const lastDoc = snapshot.docs[snapshot.docs.length - 1]; return { items, lastDoc }; } -
3
Step 3: Use Aggregation Queries for Document Counting
To count collection documents, avoid full document fetching. Use
getCountFromServer(), which consumes only 1 single read regardless of collection size:JAVASCRIPTimport { collection, getCountFromServer } from "firebase/firestore"; // Count millions of documents with exactly 1 document read cost const coll = collection(db, "orders"); const snapshot = await getCountFromServer(coll); console.log("Total orders:", snapshot.data().count); -
4
Step 4: Unsubscribe Realtime onSnapshot Listeners
In frontend frameworks (React/Vue), lingering listeners continue streaming document mutations indefinitely:
JAVASCRIPT// Inside React useEffect: useEffect(() => { const unsubscribe = onSnapshot(doc(db, "chats", chatId), (doc) => { setMessages(doc.data()); }); // Teardown listener on component unmount return () => unsubscribe(); }, [chatId]);
❓ Frequently Asked Questions (FAQ)
What time does the daily Spark quota reset?
Firestore daily quotas reset at midnight Pacific Time (PST/PDT), which corresponds to 00:00 UTC-8.
Do cached reads consume daily quota limits?
No. Reads satisfied from IndexedDB client cache are completely free and consume zero network read quota.
Prevention Advice
Recommended security practices:
- Configure Google Cloud Billing Alerts: Set up automated email budget thresholds in Google Cloud Console to catch anomalous usage spikes early.
- Denormalize relational aggregates: Maintain summary counters inside parent documents to bypass multi-document read traversals.