Firebase throws RESOURCE_EXHAUSTED when your project hits quota limits on reads, writes, or storage. Enable billing, optimize your queries to reduce consumption, or request a quota increase from Google Cloud Console.
Firebase enforces quotas on operations like reads, writes, deletes, and storage to ensure fair resource usage and maintain service reliability across all users. When your project exceeds these limits, Firebase returns the RESOURCE_EXHAUSTED error and blocks further operations until the quota resets (typically daily around midnight Pacific time) or you increase the quota. The error can occur in Firestore, Cloud Functions, Cloud Messaging, or Cloud Storage depending on which service you're using. For free (Spark) plan users, quotas are especially tight and reset daily. For billable (Blaze) projects, you can request quota increases through Google Cloud Console, but you should optimize your usage first to avoid unexpected charges.
Navigate to the Google Cloud Console, select your Firebase project, then go to APIs & Services > Quotas. Filter by the service that failed (Firestore, Cloud Functions, Cloud Messaging, etc.). You'll see current usage and the quota limit. This tells you exactly what resource to optimize or increase.
If you're on a Spark plan, also note that quotas reset daily around midnight Pacific time. For immediate relief, you can:
1. Wait for the daily quota reset
2. Switch to a Blaze (billable) plan for higher limits
3. Optimize your usage to stay within limits
Spark (free) plan has severe quota limits. To unlock higher limits, upgrade to a Blaze plan:
1. Open Firebase Console > Project Settings > Billing
2. Click "Upgrade to Blaze plan"
3. Add a billing method
4. Confirm the upgrade
Once billing is enabled, you'll have access to much higher quotas and can request increases up to +25% (or more with advance notice). You'll only be charged for usage above the free tier thresholds, so small projects remain free.
Firestore quotas are mainly about read and write operations. Reduce your query consumption:
// BAD: Fetches all documents then filters in memory
const users = await db.collection('users').get();
const active = users.docs.filter(doc => doc.data().active === true);
// GOOD: Let Firestore filter, reducing reads
const active = await db
.collection('users')
.where('active', '==', true)
.get();
// BAD: Fetches entire documents
const users = await db.collection('users').get();
// GOOD: Fetch only needed fields
const names = await db
.collection('users')
.select('name')
.get();Also add pagination limits to avoid large result sets:
const page = await db
.collection('users')
.limit(50) // Limit to 50 reads per query
.get();Cache frequently accessed data in memory or Redis to reduce read quota consumption:
import Redis from 'redis';
const redis = Redis.createClient();
async function getCachedUser(id: string) {
// Check cache first (no quota hit)
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
// Cache miss: fetch from Firestore (quota hit)
const doc = await db.collection('users').doc(id).get();
const data = doc.data();
// Store in cache for 5 minutes
await redis.setEx(`user:${id}`, 300, JSON.stringify(data));
return data;
}Caching is especially effective for user profiles, configuration data, and frequently queried collections.
If writing many documents, batch them and add delays to avoid hot-spotting:
async function batchWrite(documents: any[]) {
const batchSize = 100;
for (let i = 0; i < documents.length; i += batchSize) {
const batch = db.batch();
const slice = documents.slice(i, i + batchSize);
slice.forEach(doc => {
batch.set(db.collection('data').doc(), doc);
});
await batch.commit();
// Add delay between batches
await new Promise(resolve => setTimeout(resolve, 1000));
}
}This prevents writes to the same hot-spot from firing too fast.
Once billing is enabled, you can request quota increases:
1. Go to Google Cloud Console > APIs & Services > Quotas
2. Find the quota you want to increase (e.g., "Firestore Database Read Operations")
3. Check the quota
4. Click "Edit Quotas" at the top
5. Enter the new limit (you can request up to +25% in most cases)
6. Fill in your contact information and justification
7. Submit
For larger increases or time-sensitive requests (like a product launch), submit at least 30 days in advance. Google will review and approve or counter-offer within a few business days.
Firestore-specific notes:
- Hot-spotting is a leading cause: avoid rapid updates to the same document. Distribute writes across multiple documents or subcollections.
- Android SDK has a 2000-item result limit; queries returning more items fail with RESOURCE_EXHAUSTED. Paginate results or filter earlier.
- Transactions and batches count as individual operations, so large batches consume more quota.
- Real-time listeners (onSnapshot) count as reads on every document change, not just the initial fetch. Avoid broad queries with listeners.
Cloud Functions-specific notes:
- Quota exhaustion blocks all functions in the project, not just the one that hit the limit. One runaway function can prevent others from executing.
- Memory and CPU quotas are per-region. Distribute functions across regions if hitting limits.
Cloud Messaging-specific notes:
- FCM quotas reset every 5 minutes for per-target limits. Throttle batches across multiple 5-minute windows.
- Spark plan FCM quota is ~500K messages/day; Blaze is unlimited (with soft rate limits).
Storage-specific notes:
- Free tier is 5 GB; Blaze charges ~$0.018/GB. Delete old backups and compress large files to reduce consumption.
- Use lifecycle rules (set storage.rules) to auto-delete temporary files after N days.
Callable Functions: INTERNAL - Unhandled exception
How to fix "Callable Functions: INTERNAL - Unhandled exception" in Firebase
auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options
How to fix "auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options" in Firebase
Hosting: CORS configuration not set up properly
How to fix CORS configuration in Firebase Hosting
auth/reserved-claims: Custom claims use reserved OIDC claim names
How to fix "reserved claims" error when setting custom claims in Firebase
Callable Functions: UNAUTHENTICATED - Invalid credentials
How to fix "UNAUTHENTICATED - Invalid credentials" in Firebase Callable Functions