WARNING

How to Fix Nginx 504 Gateway Time-out Error

Quick Fix Summary

TL;DR

Increase proxy_read_timeout and fastcgi_read_timeout directives in your Nginx configuration.

Nginx returns a 504 Gateway Time-out when it fails to receive a timely response from an upstream server (like PHP-FPM, Node.js, or another proxy). This indicates the backend service is taking longer than Nginx's configured timeout to process the request.

Diagnosis & Causes

  • Upstream server (e.g., PHP-FPM) is overloaded or hung.
  • Network latency or connectivity issues to the backend.
  • Database queries or external API calls are too slow.
  • Insufficient resources (CPU, memory) on the application server.
  • Nginx proxy or FastCGI timeout values are set too low.
  • Recovery Steps

    1

    Step 1: Increase Nginx Proxy Timeout Directives

    The primary fix is to increase the timeout Nginx waits for a response from the upstream server. Apply this in the `http`, `server`, or `location` block.

    nginx
    location / {
        proxy_pass http://backend_server;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 300s; # Increase this value (e.g., 300 seconds)
        send_timeout 60s;
    }
    2

    Step 2: Increase FastCGI Timeout for PHP-FPM

    If Nginx proxies to PHP-FPM via FastCGI, increase the `fastcgi_read_timeout` directive in your configuration.

    nginx
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_read_timeout 300s; # Increase from default 60s
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    3

    Step 3: Check and Tune Upstream Server (PHP-FPM)

    Ensure your PHP-FPM pool configuration can handle the load and has appropriate timeouts. Key settings are `request_terminate_timeout` and `max_children`.

    bash
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 5
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    request_terminate_timeout = 300 # Must be >= Nginx's fastcgi_read_timeout
    request_slowlog_timeout = 10
    4

    Step 4: Analyze Upstream Server Logs & Performance

    Identify the slow component. Check application, database, and external service logs for errors or long-running operations.

    bash
    # Tail PHP-FPM slow log (if configured)
    tail -f /var/log/php8.1-fpm.log.slow
    # Check for slow database queries (MySQL example)
    SHOW PROCESSLIST;
    # Monitor server resources in real-time
    top -u www-data
    5

    Step 5: Implement Health Checks and Failover

    For critical production, configure Nginx to mark slow upstreams as unhealthy and use backup servers.

    nginx
    upstream backend {
        server backend1.example.com max_fails=3 fail_timeout=30s;
        server backend2.example.com backup;
    }
    6

    Step 6: Test Configuration and Reload Nginx

    Always test your configuration syntax before applying changes to avoid taking down the server.

    bash
    sudo nginx -t
    sudo systemctl reload nginx  # Or: sudo service nginx reload

    Architect's Pro Tip

    "Don't just set timeouts to 24 hours. Use increased timeouts (e.g., 300s) as a temporary shield while you use the slow logs to find and fix the actual root cause in your application code or database."

    Frequently Asked Questions

    What's the difference between proxy_read_timeout and fastcgi_read_timeout?

    Use `proxy_read_timeout` when Nginx proxies to another HTTP server (Node.js, Apache, another Nginx). Use `fastcgi_read_timeout` when Nginx communicates with a FastCGI process like PHP-FPM.

    I increased the timeouts but still get 504 errors. What next?

    The bottleneck is now definitively upstream of Nginx. Investigate your application server's resource usage (CPU, RAM, I/O), database query performance, and calls to external APIs or microservices. Enable detailed logging in your app.

    Can a 504 error be caused by the client?

    No. A 504 Gateway Time-out is strictly a server-side error. It means Nginx (the gateway) did not get a response from the upstream server within its configured timeframe. Client-side slowness would result in a different error or timeout.

    Related Nginx Guides