Firebase Rate Limit & Auth Errors: Fix 401, 403, 429, 502, 503 Fast
Fix Firebase rate limit, 401, 403, 502, 503, token expired, and connection refused errors with step-by-step diagnostic commands and proven solutions.
- Firebase rate limiting (HTTP 429) triggers when your app exceeds per-project or per-IP quotas — default is 1 write/second per document in Firestore and 100 simultaneous connections for Realtime Database
- 401 Unauthorized and 403 Forbidden errors almost always trace to expired ID tokens, missing Firebase App Check configuration, or misconfigured Security Rules that silently block authenticated users
- 502 and 503 errors are Firebase-side infrastructure issues but can be worsened by missing exponential backoff — always wrap Firebase calls in retry logic with jitter
- Quick fix sequence: (1) verify token freshness with firebase.auth().currentUser.getIdToken(true), (2) check Firebase Status Dashboard at status.firebase.google.com, (3) audit Security Rules in the Firebase Console, (4) implement exponential backoff for all write operations
| Method | When to Use | Time to Apply | Risk |
|---|---|---|---|
| Force-refresh ID token via getIdToken(true) | firebase 401 / firebase token expired / firebase invalid token | < 5 minutes | Low — safe client-side call |
| Audit & redeploy Security Rules | firebase 403 / firebase unauthorized | 10–30 minutes | Medium — wrong rules lock out all users |
| Implement exponential backoff with jitter | firebase rate limited / firebase rate limit (429) | 30–60 minutes | Low — improves resilience |
| Increase Firestore quota via GCP Console | firebase rate limit on writes at scale | 1–2 days (quota review) | Low — Google reviews request |
| Enable Firebase App Check | firebase 401 on valid tokens, abuse mitigation | 1–2 hours | Medium — must enroll all clients first |
| Switch to Firebase Emulator for local debug | firebase connection refused / firebase timeout in dev | 15 minutes | None — isolated environment |
| Check & rotate service account keys | firebase authentication failed in server SDKs | 20 minutes | Medium — rotating keys breaks existing deployments |
Understanding Firebase Rate Limit and Auth Errors
Firebase surfaces a cluster of related HTTP status codes that developers frequently conflate. Understanding exactly which layer is failing is the fastest path to a fix.
| Error | HTTP Code | Layer | Primary Cause |
|---|---|---|---|
| firebase rate limit | 429 | Firestore / RTDB quota | Exceeded per-document or project write quota |
| firebase 401 | 401 | Firebase Auth / Security Rules | Token missing, expired, or malformed |
| firebase 403 | 403 | Firebase Security Rules | Token valid but rules deny access |
| firebase 502 | 502 | Firebase infrastructure | Bad gateway — upstream Firebase service error |
| firebase 503 | 503 | Firebase infrastructure | Service temporarily unavailable |
| firebase timeout | — | Network / Firestore | Long-polling timeout or slow query |
| firebase connection refused | — | Network / Emulator | Wrong endpoint, emulator not running, firewall |
Step 1: Confirm Which Error You Actually Have
The Firebase JavaScript SDK surfaces errors through the error.code property. Server-side SDKs use gRPC status codes. Always log both:
// Client SDK — Firestore example
try {
await db.collection('items').doc('abc').set(data);
} catch (err) {
console.error('code:', err.code); // e.g. "resource-exhausted"
console.error('message:', err.message); // e.g. "Quota exceeded."
}
Firestore maps gRPC codes to these string codes:
resource-exhausted→ rate limit (429)permission-denied→ 403 / Security Rulesunauthenticated→ 401 / missing or expired tokenunavailable→ 503 / transient Firebase outagedeadline-exceeded→ timeout
Step 2: Diagnose Authentication Errors (401 / firebase token expired / firebase invalid token)
The most common cause is an expired ID token. Firebase ID tokens expire after 1 hour. The SDK auto-refreshes them in the background, but this fails in service workers, background tabs, or server environments.
Check token expiry on the client:
const user = firebase.auth().currentUser;
if (!user) {
console.log('No authenticated user — redirect to login');
} else {
// Force-refresh the token
const token = await user.getIdToken(/* forceRefresh */ true);
console.log('Fresh token obtained:', token.substring(0, 20) + '...');
// Decode without verification to inspect claims
const payload = JSON.parse(atob(token.split('.')[1]));
console.log('Expires at:', new Date(payload.exp * 1000));
console.log('Issued at:', new Date(payload.iat * 1000));
}
Server-side: verify token with Admin SDK:
const admin = require('firebase-admin');
try {
const decoded = await admin.auth().verifyIdToken(idToken);
console.log('UID:', decoded.uid);
} catch (err) {
if (err.code === 'auth/id-token-expired') {
// Client must call getIdToken(true) and retry
return res.status(401).json({ error: 'TOKEN_EXPIRED' });
}
if (err.code === 'auth/argument-error') {
// Malformed token — client bug or tampering
return res.status(401).json({ error: 'INVALID_TOKEN' });
}
}
Step 3: Diagnose Authorization Errors (403 / firebase unauthorized)
A 403 means the token is valid but Firestore Security Rules deny the operation. This is extremely common after deploying rules changes.
Quick Security Rules test in the Firebase Console:
- Open Firebase Console → Firestore → Rules → Rules Playground
- Set Auth State to authenticated with your test UID
- Simulate the exact read/write operation that is failing
Common broken rule patterns:
// BAD — accidentally denies all authenticated users
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid = userId; // = should be ==
}
}
}
// GOOD — correct equality check
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
Step 4: Diagnose Rate Limiting (firebase rate limited / firebase rate limit)
Firestore rate limits are per-document: 1 write per second sustained, with short bursts allowed. The Realtime Database has a 100 simultaneous connection limit on the Spark (free) plan.
Find which documents are hot:
# Use gcloud to check Firestore operation counts
gcloud firestore operations list --project=YOUR_PROJECT_ID
# Check current quotas in GCP Console
gcloud services quota list --service=firestore.googleapis.com --project=YOUR_PROJECT_ID
Implement exponential backoff (the definitive fix):
async function writeWithRetry(docRef, data, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
await docRef.set(data);
return; // success
} catch (err) {
if (err.code !== 'resource-exhausted' || attempt === maxRetries - 1) {
throw err; // not a rate limit error, or out of retries
}
const backoffMs = Math.min(1000 * Math.pow(2, attempt), 30000);
const jitter = Math.random() * 1000;
console.warn(`Rate limited. Retrying in ${backoffMs + jitter}ms (attempt ${attempt + 1})`);
await new Promise(resolve => setTimeout(resolve, backoffMs + jitter));
}
}
}
Batch writes to reduce document contention:
// Instead of 500 individual writes, use a batch
const batch = db.batch();
for (const item of items) {
const ref = db.collection('items').doc(item.id);
batch.set(ref, item);
}
await batch.commit(); // counts as fewer quota operations
Step 5: Diagnose Infrastructure Errors (firebase 502 / firebase 503)
502 and 503 errors originate from Firebase's servers. Check the status dashboard first before spending time debugging your code:
- https://status.firebase.google.com — real-time Firebase status
- https://status.cloud.google.com — underlying GCP infrastructure
If there is no active incident, a 503 can also indicate you've hit a project-level quota that requires a GCP quota increase request.
Step 6: Fix firebase connection refused and firebase timeout
In development — Emulator Suite not running:
# Start the emulator suite
firebase emulators:start --only firestore,auth
# Verify emulators are listening
curl http://localhost:8080 # Firestore emulator UI
curl http://localhost:9099 # Auth emulator
Ensure your app points to the emulator:
if (location.hostname === 'localhost') {
db.useEmulator('localhost', 8080);
firebase.auth().useEmulator('http://localhost:9099');
}
Firestore timeout on large queries:
// Add query limits and indexes to prevent timeout
const snapshot = await db.collection('logs')
.where('userId', '==', uid)
.orderBy('createdAt', 'desc')
.limit(50) // Always limit large collections
.get();
If you see The query requires an index, follow the link in the error message to create the composite index in the Firebase Console.
Step 7: Fix firebase authentication failed in Server SDKs
Server SDKs (Node.js, Python, Go, Java) authenticate using a service account JSON key file or Application Default Credentials (ADC).
# Verify ADC is configured correctly
gcloud auth application-default print-access-token
# Or set explicit service account path
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccountKey.json"
# Validate the service account has required roles
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--flatten='bindings[].members' \
--filter='bindings.members:serviceAccount:YOUR_SA_EMAIL'
Required IAM roles for Firebase Admin SDK:
roles/firebase.admin— full Firebase accessroles/datastore.user— Firestore read/write onlyroles/firebaseauth.admin— Auth management only
Frequently Asked Questions
#!/usr/bin/env bash
# Firebase Error Diagnostic Script
# Run this script to quickly identify auth, quota, and connectivity issues
set -euo pipefail
PROJECT_ID="${FIREBASE_PROJECT_ID:-YOUR_PROJECT_ID}"
echo "=== 1. Check Firebase project configuration ==="
firebase projects:list 2>/dev/null | grep "$PROJECT_ID" || echo "WARNING: project not found in firebase CLI"
echo ""
echo "=== 2. Verify Application Default Credentials ==="
if gcloud auth application-default print-access-token > /dev/null 2>&1; then
echo "OK: ADC token obtained successfully"
else
echo "ERROR: ADC not configured — run: gcloud auth application-default login"
fi
echo ""
echo "=== 3. Test Firestore REST API connectivity ==="
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $(gcloud auth print-access-token 2>/dev/null || echo 'NO_TOKEN')" \
"https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents?pageSize=1")
echo "Firestore REST API HTTP response: $HTTP_CODE"
case $HTTP_CODE in
200) echo "OK: Firestore accessible" ;;
401) echo "ERROR: Unauthenticated — check ADC or service account key" ;;
403) echo "ERROR: Permission denied — verify IAM roles for service account" ;;
429) echo "ERROR: Rate limited — implement backoff or request quota increase" ;;
503) echo "ERROR: Firebase service unavailable — check https://status.firebase.google.com" ;;
*) echo "UNKNOWN: HTTP $HTTP_CODE" ;;
esac
echo ""
echo "=== 4. Check Firebase Auth service ==="
AUTH_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
"https://identitytoolkit.googleapis.com/v1/projects/$PROJECT_ID/oobCodes" \
-H "Content-Type: application/json" -d '{}')
echo "Firebase Auth API HTTP response: $AUTH_CODE"
# 400 is expected (missing body) — means the service is reachable
[[ $AUTH_CODE == 400 ]] && echo "OK: Firebase Auth service is reachable"
[[ $AUTH_CODE == 503 ]] && echo "ERROR: Firebase Auth unavailable"
echo ""
echo "=== 5. Check Firestore quota usage ==="
gcloud firestore operations list --project="$PROJECT_ID" --limit=5 2>/dev/null \
|| echo "SKIP: gcloud not configured or insufficient permissions"
echo ""
echo "=== 6. Emulator health check (if running locally) ==="
curl -s --connect-timeout 2 http://localhost:8080 > /dev/null 2>&1 \
&& echo "OK: Firestore emulator running on :8080" \
|| echo "INFO: Firestore emulator not detected on :8080"
curl -s --connect-timeout 2 http://localhost:9099 > /dev/null 2>&1 \
&& echo "OK: Auth emulator running on :9099" \
|| echo "INFO: Auth emulator not detected on :9099"
echo ""
echo "=== Diagnostic complete ==="Error Medic Editorial
Error Medic Editorial is a team of senior DevOps and SRE engineers who have collectively spent thousands of hours debugging cloud-native infrastructure across Firebase, GCP, AWS, and Azure. Our guides prioritize real commands, verified error codes, and production-tested solutions over theoretical explanations.
Sources
- https://firebase.google.com/docs/firestore/quotas
- https://firebase.google.com/docs/auth/admin/errors
- https://firebase.google.com/docs/rules/manage-deploy
- https://cloud.google.com/firestore/docs/best-practices
- https://stackoverflow.com/questions/49692745/firestore-resource-exhausted-quota-exceeded
- https://github.com/firebase/firebase-js-sdk/issues/1133
- https://status.firebase.google.com