Error Medic

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.

Last updated:
Last verified:
2,132 words
Key Takeaways
  • 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
Fix Approaches Compared
MethodWhen to UseTime to ApplyRisk
Force-refresh ID token via getIdToken(true)firebase 401 / firebase token expired / firebase invalid token< 5 minutesLow — safe client-side call
Audit & redeploy Security Rulesfirebase 403 / firebase unauthorized10–30 minutesMedium — wrong rules lock out all users
Implement exponential backoff with jitterfirebase rate limited / firebase rate limit (429)30–60 minutesLow — improves resilience
Increase Firestore quota via GCP Consolefirebase rate limit on writes at scale1–2 days (quota review)Low — Google reviews request
Enable Firebase App Checkfirebase 401 on valid tokens, abuse mitigation1–2 hoursMedium — must enroll all clients first
Switch to Firebase Emulator for local debugfirebase connection refused / firebase timeout in dev15 minutesNone — isolated environment
Check & rotate service account keysfirebase authentication failed in server SDKs20 minutesMedium — 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 Rules
  • unauthenticated → 401 / missing or expired token
  • unavailable → 503 / transient Firebase outage
  • deadline-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:

  1. Open Firebase Console → Firestore → Rules → Rules Playground
  2. Set Auth State to authenticated with your test UID
  3. 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:

  1. https://status.firebase.google.com — real-time Firebase status
  2. 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 access
  • roles/datastore.user — Firestore read/write only
  • roles/firebaseauth.admin — Auth management only

Frequently Asked Questions

bash
#!/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 ==="
E

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

Related Articles in Firebase

Explore More API Errors Guides