HTTP

504 - Gateway Timeout

Getting a 504 Gateway Timeout means the gateway or proxy waited too long for the upstream server to respond—the backend took longer than the gateway's timeout, the request is still processing, or the backend is hung. This server-side error (5xx) happens when infrastructure (load balancer, reverse proxy) times out waiting for the application server. Most common when backend operations are slow (database queries, external API calls), but also appears when gateway timeout settings are too aggressive, network latency is high, or the backend is overloaded and can't respond in time.

#Common Causes

  • Frontend: Client can't fix 504s directly, but retries can help if it's transient. Long-running requests may need timeout handling.
  • Backend: Slow database queries (missing indexes, full table scans). Long-running operations (file processing, data exports). External API calls timeout. Application hangs or deadlocks. Resource exhaustion (CPU, memory) slows processing.
  • Infrastructure: Gateway timeout too short (proxy_read_timeout, proxy_send_timeout). Network latency between gateway and backend. Upstream server overloaded and slow to respond. Load balancer health check timeout.

Solutions

  1. 1Step 1: Diagnose - Check gateway logs for timeout messages ("upstream timed out"). Review gateway timeout settings (Nginx proxy_read_timeout). Check backend response times in monitoring. Look for slow database queries.
  2. 2Step 2: Diagnose - Check backend application logs for slow operations. Review database query performance. Check external API response times. Examine resource usage (CPU, memory).
  3. 3Step 3: Fix - Client-side: Implement longer timeouts for long-running requests. Show progress indicators for operations that take time. Implement retry logic with longer delays. Use polling for async operations instead of waiting.
  4. 4Step 4: Fix - Server-side: Optimize slow database queries (add indexes, optimize joins). Implement async processing for long operations (queue jobs). Add timeouts to external API calls. Fix application hangs or deadlocks.
  5. 5Step 5: Fix - Infrastructure: Increase gateway timeout settings (proxy_read_timeout 60s, proxy_send_timeout 60s). Optimize network connectivity. Scale backend if overloaded. Configure appropriate health check timeouts.

</>Code Examples

Fetch API: Handle Long-Running Requests
1// Client-side: Handle 504 with longer timeouts and retries
2async function fetchWithTimeout(url, options = {}, timeout = 60000) {
3const controller = new AbortController();
4  const timeoutId = setTimeout(() => controller.abort(), timeout);
5  
6  try {
7    const response = await fetch(url, {
8      ...options,
9      signal: controller.signal,
10    });
11    
12    clearTimeout(timeoutId);
13    
14    if (response.status === 504) {
15      // Gateway timeout - might be transient, retry once
16      console.warn('Gateway timeout, retrying...');
17      return fetchWithTimeout(url, options, timeout);
18    }
19    
20    return response;
21  } catch (error) {
22    clearTimeout(timeoutId);
23    
24    if (error.name === 'AbortError') {
25      throw new Error('Request timeout');
26    }
27    throw error;
28  }
29}
30
31// For long-running operations, use polling instead
32async function startLongOperation() {
33  // Start async operation
34  const startResponse = await fetch('/api/operations/start', {
35    method: 'POST',
36    headers: { 'Content-Type': 'application/json' },
37    body: JSON.stringify({ type: 'export' }),
38  });
39  
40  const { operationId } = await startResponse.json();
41  
42  // Poll for completion instead of waiting
43  while (true) {
44    const statusResponse = await fetch(`/api/operations/${operationId}`);
45    const { status, result } = await statusResponse.json();
46    
47    if (status === 'completed') {
48      return result;
49    } else if (status === 'failed') {
50      throw new Error('Operation failed');
51    }
52    
53    // Wait before next poll
54    await new Promise(resolve => setTimeout(resolve, 2000));
55  }
56}
Express.js: Optimize Slow Operations
1// Server-side: Optimize operations to prevent timeouts
2const express = require('express');
3const app = express();
4
5// Add timeout middleware
6const timeout = (ms) => (req, res, next) => {
7  req.setTimeout(ms, () => {
8    res.status(504).json({
9      error: 'Gateway Timeout',
10      message: 'Request took too long to process',
11    });
12  });
13  next();
14};
15
16// Optimize slow database queries
17app.get('/api/users', timeout(30000), async (req, res) => {
18  try {
19    // Use indexed queries, limit results, add pagination
20    const users = await db.users
21      .find()
22      .select('name email') // Only select needed fields
23      .limit(100) // Limit results
24      .skip((req.query.page || 0) * 100)
25      .lean(); // Faster queries
26    
27    res.json(users);
28  } catch (error) {
29    console.error('Database error:', error);
30    res.status(500).json({ error: 'Internal Server Error' });
31  }
32});
33
34// For long-running operations, use async processing
35app.post('/api/export', async (req, res) => {
36  // Start async job instead of processing synchronously
37  const jobId = await queue.add('export', {
38    userId: req.user.id,
39    filters: req.body.filters,
40  });
41  
42  res.status(202).json({
43    message: 'Export started',
44    jobId: jobId,
45    statusUrl: `/api/jobs/${jobId}`,
46  });
47});
48
49// Check job status
50app.get('/api/jobs/:id', async (req, res) => {
51  const job = await queue.getJob(req.params.id);
52  const status = await job.getState();
53  
54  res.json({
55    id: job.id,
56    status: status,
57    progress: job.progress,
58    result: status === 'completed' ? job.returnvalue : null,
59  });
60});
Nginx: Increase Gateway Timeouts
1# Nginx: Configure longer timeouts for slow operations
2upstream backend {
3    server backend1:3000;
4    server backend2:3000;
5    keepalive 32;
6}
7
8server {
9    listen 80;
10    server_name api.example.com;
11    
12    location /api/ {
13        proxy_pass http://backend;
14        proxy_set_header Host $host;
15        proxy_set_header X-Real-IP $remote_addr;
16        
17        # Increase timeouts for slow operations
18        proxy_connect_timeout 10s;
19        proxy_send_timeout 60s;      # Increased from default 60s
20        proxy_read_timeout 60s;      # Increased from default 60s
21        
22        # Buffer settings for large responses
23        proxy_buffering on;
24        proxy_buffer_size 4k;
25        proxy_buffers 8 4k;
26        proxy_busy_buffers_size 8k;
27        
28        # Don't fail on timeouts immediately
29        proxy_next_upstream timeout;
30        proxy_next_upstream_tries 2;
31    }
32    
33    # Special location for long-running operations
34    location /api/export {
35        proxy_pass http://backend;
36        proxy_read_timeout 300s;    # 5 minutes for exports
37        proxy_send_timeout 300s;
38    }
39}

Related Errors

Provider Information

This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.

504 - Gateway Timeout | HTTP Error Reference | Error Code Reference