How to fix messaging/UNAVAILABLE: Server overloaded in Firebase

FirebaseINTERMEDIATEMEDIUMUpdated Dec 18, 2025ยท 228 views

The UNAVAILABLE error in Firebase Cloud Messaging indicates that the FCM server is temporarily overloaded or under maintenance and cannot process your request at this time.

Quick fix

Fixes messaging/UNAVAILABLE

// Node.js example with Firebase Admin SDK
const admin = require('firebase-admin');

async function sendWithRetry(message, maxRetries = 5) {
  let retryCount = 0;
  let delay = 1000; // Start with 1 second

  while (retryCount < maxRetries) {
    try {
      const response = await admin.messaging().send(message);
      console.log('Successfully sent message:', response);
      return response;
    } catch (error) {
      if (error.code === 'messaging/unavailable' ||
          error.code === 'messaging/internal-error') {
        retryCount++;

        if (retryCount >= maxRetries) {
          console.error('Max retries reached:', error);
          throw error;
        }

        // Add jitter (randomness) to prevent thundering herd
        const jitter = Math.random() * 1000;
        const waitTime = delay + jitter;

        console.log(`Retry ${retryCount}/${maxRetries} after ${Math.round(waitTime)}ms`);
        await new Promise(resolve => setTimeout(resolve, waitTime));

        // Exponential backoff: double the delay each time
        delay *= 2;
      } else {
        // Different error, don't retry
        throw error;
      }
    }
  }
}

// Usage
const message = {
  notification: {
    title: 'Hello',
    body: 'World'
  },
  token: 'device-token-here'
};

sendWithRetry(message);
  1. Implement exponential backoff retry logic
  2. Check the Firebase Status Dashboard
  3. Honor the Retry-After header if present
  4. Implement rate limiting for your message sending
firebase โ€” error
// Node.js example with Firebase Admin SDK
const admin = require('firebase-admin');
async function sendWithRetry(message, maxRetries = 5) {
let retryCount = 0;
let delay = 1000; // Start with 1 second
while (retryCount < maxRetries) {
try {
const response = await admin.messaging().send(message);
console.log('Successfully sent message:', response);
return response;
} catch (error) {
if (error.code === 'messaging/unavailable' ||
error.code === 'messaging/internal-error') {
retryCount++;
if (retryCount >= maxRetries) {
console.error('Max retries reached:', error);
throw error;
}
// Add jitter (randomness) to prevent thundering herd
const jitter = Math.random() * 1000;
const waitTime = delay + jitter;
console.log(`Retry ${retryCount}/${maxRetries} after ${Math.round(waitTime)}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
// Exponential backoff: double the delay each time
delay *= 2;
} else {
// Different error, don't retry
throw error;
}
}
}
}
// Usage
const message = {
notification: {
title: 'Hello',
body: 'World'
},
token: 'device-token-here'
};
sendWithRetry(message);
messaging/UNAVAILABLE: Server overloaded

What this error means

The "messaging/UNAVAILABLE: Server overloaded" error occurs when Firebase Cloud Messaging (FCM) servers are experiencing high load or undergoing maintenance. This is a server-side error (HTTP 503 Service Unavailable) that indicates the FCM infrastructure cannot currently process your notification request. This error is typically temporary and falls into the 500-599 range of HTTP status codes, which represent server-side failures. Unlike client errors (400-499), this means your request format is correct, but the service cannot fulfill it at this moment due to capacity constraints. The error may also appear alongside HTTP 429 responses during severe overload situations, where the system throttles incoming requests to protect infrastructure stability.

Typical symptoms

  • FCM API calls fail with "messaging/UNAVAILABLE" error code
  • Push notifications are not delivered to devices
  • Intermittent failures when sending messages, with some succeeding and others failing
  • Server returns HTTP 503 status code in response
  • Error messages mention "Server overloaded" or similar capacity issues
  • Failures occur across multiple devices or tokens simultaneously

Common causes

  1. FCM servers are experiencing unusually high traffic volume
  2. Google infrastructure is performing scheduled or emergency maintenance
  3. Regional outages affecting Firebase Cloud Messaging service
  4. Distributed denial-of-service (DDoS) mitigation causing temporary unavailability
  5. Your application is sending an excessive burst of messages without proper rate limiting
  6. Network connectivity issues between your server and FCM endpoints

How to fix "messaging/UNAVAILABLE: Server overloaded"

1Implement exponential backoff retry logic

Add retry logic with exponential backoff to handle temporary server overload gracefully. This is the recommended approach from Firebase documentation.

javascript
// Node.js example with Firebase Admin SDK
const admin = require('firebase-admin');

async function sendWithRetry(message, maxRetries = 5) {
  let retryCount = 0;
  let delay = 1000; // Start with 1 second

  while (retryCount < maxRetries) {
    try {
      const response = await admin.messaging().send(message);
      console.log('Successfully sent message:', response);
      return response;
    } catch (error) {
      if (error.code === 'messaging/unavailable' ||
          error.code === 'messaging/internal-error') {
        retryCount++;

        if (retryCount >= maxRetries) {
          console.error('Max retries reached:', error);
          throw error;
        }

        // Add jitter (randomness) to prevent thundering herd
        const jitter = Math.random() * 1000;
        const waitTime = delay + jitter;

        console.log(`Retry ${retryCount}/${maxRetries} after ${Math.round(waitTime)}ms`);
        await new Promise(resolve => setTimeout(resolve, waitTime));

        // Exponential backoff: double the delay each time
        delay *= 2;
      } else {
        // Different error, don't retry
        throw error;
      }
    }
  }
}

// Usage
const message = {
  notification: {
    title: 'Hello',
    body: 'World'
  },
  token: 'device-token-here'
};

sendWithRetry(message);

The exponential backoff pattern uses delays like: 1s, 2s, 4s, 8s, 16s. Adding jitter prevents all clients from retrying simultaneously.

2Check the Firebase Status Dashboard

Before implementing complex solutions, verify if there's a known outage affecting FCM services.

1. Visit the Firebase Status Dashboard: https://status.firebase.google.com/
2. Look for the "Cloud Messaging" section
3. Check for any active incidents or maintenance windows

If there's an ongoing incident, wait for Google to resolve it. Your retry logic will automatically succeed once service is restored.

3Honor the Retry-After header if present

FCM may include a Retry-After header in the response to indicate when you should retry. Respect this value instead of using your own backoff calculation.

javascript
async function sendWithRetryAfterHeader(message) {
  try {
    const response = await admin.messaging().send(message);
    return response;
  } catch (error) {
    if (error.code === 'messaging/unavailable') {
      // Check if there's a Retry-After header in the error details
      const retryAfter = error.errorInfo?.retry_after;

      if (retryAfter) {
        const waitMs = parseInt(retryAfter) * 1000;
        console.log(`Server requested retry after ${retryAfter}s`);
        await new Promise(resolve => setTimeout(resolve, waitMs));

        // Retry once after waiting
        return await admin.messaging().send(message);
      }
    }
    throw error;
  }
}

Always prioritize the server's suggested retry time over your own logic.

4Implement rate limiting for your message sending

Prevent contributing to FCM server overload by implementing proper rate limiting on your side.

javascript
// Example using p-queue for rate limiting
const PQueue = require('p-queue').default;

class FCMSender {
  constructor() {
    // Limit to 100 concurrent requests
    this.queue = new PQueue({
      concurrency: 100,
      interval: 1000, // 1 second
      intervalCap: 500 // Max 500 messages per second
    });
  }

  async sendMessage(message) {
    return this.queue.add(async () => {
      return await admin.messaging().send(message);
    });
  }

  async sendBatch(messages) {
    const promises = messages.map(msg => this.sendMessage(msg));
    return Promise.allSettled(promises);
  }
}

// Usage
const sender = new FCMSender();
await sender.sendBatch(arrayOfMessages);

This prevents sudden bursts of requests that could contribute to overload situations.

5Use batch sending for multiple notifications

When sending to multiple devices, use FCM's batch APIs to reduce request overhead and improve efficiency.

javascript
// Send to multiple devices efficiently
async function sendBatchNotifications(tokens, notification) {
  const messages = tokens.map(token => ({
    notification: notification,
    token: token
  }));

  // Send up to 500 messages at once
  const batchSize = 500;
  const results = [];

  for (let i = 0; i < messages.length; i += batchSize) {
    const batch = messages.slice(i, i + batchSize);

    try {
      const response = await admin.messaging().sendEach(batch);
      results.push(response);

      console.log(`Batch sent: ${response.successCount} succeeded, ${response.failureCount} failed`);

      // Small delay between batches
      if (i + batchSize < messages.length) {
        await new Promise(resolve => setTimeout(resolve, 100));
      }
    } catch (error) {
      console.error('Batch send failed:', error);
      // Implement retry logic here
    }
  }

  return results;
}

Batching reduces the total number of API calls and is more efficient for FCM servers.

Advanced notes

Monitoring and Alerting

Set up monitoring to track FCM error rates and automatically alert when UNAVAILABLE errors exceed a threshold. This helps you distinguish between temporary glitches and sustained outages.

javascript
// Example monitoring setup
let unavailableCount = 0;
let totalRequests = 0;

async function sendWithMonitoring(message) {
  totalRequests++;

  try {
    return await admin.messaging().send(message);
  } catch (error) {
    if (error.code === 'messaging/unavailable') {
      unavailableCount++;

      const errorRate = unavailableCount / totalRequests;
      if (errorRate > 0.1) { // More than 10% failing
        // Alert your team
        console.error('FCM error rate exceeded 10%:', errorRate);
      }
    }
    throw error;
  }
}

Queueing System for Resilience

For production systems, consider using a message queue (like Cloud Tasks, Bull, or SQS) to store pending notifications. This allows you to retry failed sends without losing messages during extended outages.

Fallback Strategies

If FCM remains unavailable for extended periods, consider fallback notification channels:
- Email notifications for critical alerts
- SMS for time-sensitive messages
- In-app notification banners when users next open the app
- WebSockets for real-time web applications

HTTP/2 vs Legacy HTTP Protocol

The newer Firebase HTTP v1 API uses HTTP/2, which provides better connection multiplexing and error handling. If you're still using the legacy API, consider migrating to v1 for improved reliability during high-load scenarios.

Regional Considerations

FCM has regional infrastructure. If you experience persistent UNAVAILABLE errors in specific geographic regions, check if there are regional outages or network routing issues affecting connectivity to Google's infrastructure.

Frequently asked questions

What does "messaging/UNAVAILABLE" mean?
The "messaging/UNAVAILABLE: Server overloaded" error occurs when Firebase Cloud Messaging (FCM) servers are experiencing high load or undergoing maintenance. This is a server-side error (HTTP 503 Service Unavailable) that indicates the FCM infrastructure cannot currently process your notification request. This error is typically temporary and falls into the 500-599 range of HTTP status codes, which represent server-side failures.
How do I fix "messaging/UNAVAILABLE"?
The UNAVAILABLE error in Firebase Cloud Messaging indicates that the FCM server is temporarily overloaded or under maintenance and cannot process your request at this time.
What causes "messaging/UNAVAILABLE"?
FCM servers are experiencing unusually high traffic volume Google infrastructure is performing scheduled or emergency maintenance Regional outages affecting Firebase Cloud Messaging service
Is the "messaging/UNAVAILABLE" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading