503 Service Unavailable

Server Error - Server temporarily cannot handle requests

HTTP 503 Service Unavailable

What It Means

The HTTP 503 Service Unavailable status code indicates that the server is currently unable to handle the request due to temporary overloading or maintenance. This is usually a temporary condition.

Common Causes

  • Planned maintenance: Server intentionally down for updates
  • Traffic spike: More requests than the server can handle
  • Resource exhaustion: Out of memory, CPU maxed, connections full
  • Deployment in progress: Rolling update temporarily unavailable
  • Circuit breaker open: Dependency failed, blocking requests
  • Rate limiting: Server protecting itself from overload

Retry-After Header

The 503 response should include a Retry-After header to tell clients when to try again:

HTTP/1.1 503 Service Unavailable
Retry-After: 300
Content-Type: application/json

{
  "error": "Service Unavailable",
  "message": "Server is under maintenance",
  "retry_after": 300
}

Maintenance Mode Implementation

Nginx maintenance page

# Check for maintenance file
if (-f /var/www/maintenance.flag) {
    return 503;
}

error_page 503 @maintenance;

location @maintenance {
    root /var/www/html;
    rewrite ^(.*)$ /maintenance.html break;
    add_header Retry-After 3600;
}

Express.js middleware

const maintenanceMode = (req, res, next) => {
  if (process.env.MAINTENANCE_MODE === 'true') {
    res.set('Retry-After', '3600');
    return res.status(503).json({
      error: 'Service Unavailable',
      message: 'Server is under maintenance'
    });
  }
  next();
};

app.use(maintenanceMode);

503 vs Other 5xx

Code Meaning
500 Something broke (unplanned)
502 Bad response from upstream
503 Intentionally unavailable
504 Upstream took too long

Client-Side Handling

async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url);

    if (response.status === 503) {
      const retryAfter = response.headers.get('Retry-After');
      const delay = retryAfter ? parseInt(retryAfter) * 1000 : 5000;
      console.log(`Service unavailable, retrying in ${delay}ms`);
      await new Promise(r => setTimeout(r, delay));
      continue;
    }

    return response;
  }
  throw new Error('Service unavailable after retries');
}

Best Practices

  • Always include Retry-After header
  • Use friendly maintenance pages for web apps
  • Implement graceful shutdown during deployments
  • Set up health check endpoints that bypass maintenance mode
  • Notify users in advance of planned maintenance

Get notified during outages

UptimeSignal alerts you when your service becomes unavailable.

Start monitoring free →

Related Status Codes