PHP Maximum Execution Time Exceeded: How to Fix 30-Second Timeout Limits

Learn to diagnose and resolve PHP maximum execution time exceeded errors. Optimize scripts and adjust configuration for long-running PHP processes on web servers.


When your PHP application performs complex tasks, heavy database queries, large file operations, or interacts with slow external APIs, you might encounter a “PHP maximum execution time of 30 seconds exceeded” error. This frustrating timeout prevents your script from completing its work, often resulting in a blank page, an HTTP 504 Gateway Timeout error in the browser, or an error message prominently displayed in your server logs. This guide will walk you through understanding why this occurs and provide precise, step-by-step instructions to resolve it, ensuring your PHP applications can run efficiently.

Symptom & Error Signature

The most common symptom is a web page that loads indefinitely and eventually displays an error in the browser, or a blank page. The error manifests itself in various log files depending on your server configuration.

Typical Browser Output (with Nginx/Apache as proxy):

504 Gateway Timeout

Or simply a blank page with no content.

PHP Error Log (/var/log/php/error.log or similar):

[27-Jun-2026 10:30:05 UTC] PHP Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/html/your-app/index.php on line 123

Nginx Error Log (/var/log/nginx/error.log):

2026/06/27 10:30:05 [error] 1234#1234: *5678 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.1, server: yourdomain.com, request: "GET /long-running-script.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "yourdomain.com"

Apache Error Log (/var/log/apache2/error.log):

[Mon Jun 27 10:30:05.123456 2026] [proxy_fcgi:error] [pid 12345:tid 123456789] [client 192.168.1.1:12345] AH01071: Got error 'PHP message: PHP Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/html/your-app/index.php on line 123'

Root Cause Analysis

The “maximum execution time exceeded” error occurs when a PHP script runs for longer than the configured time limit. This timeout is enforced at multiple layers within a typical web server stack:

  1. max_execution_time in php.ini: This is the primary PHP directive that dictates how long a script is allowed to run. By default, it’s often set to 30 seconds. If a script exceeds this, PHP terminates it.

  2. request_terminate_timeout in PHP-FPM Pool Configuration: When using PHP-FPM (FastCGI Process Manager), this directive overrides max_execution_time for PHP-FPM processes. It defines the maximum time a single request is allowed to process. If exceeded, PHP-FPM will kill the worker process handling the request.

  3. fastcgi_read_timeout in Nginx Configuration: Nginx, acting as a reverse proxy, has its own timeout for how long it waits for a response from the FastCGI (PHP-FPM) backend. If PHP-FPM is processing a long request, but Nginx’s timeout is shorter, Nginx might terminate the connection and return a 504 Gateway Timeout even before PHP finishes or hits its own limit.

  4. Timeout in Apache Configuration: Similarly, Apache’s Timeout directive dictates how long it will wait for various events, including receiving data from a backend like mod_php or mod_proxy_fcgi.

Common Scenarios Leading to Timeouts:

  • Inefficient Code: Unoptimized loops, complex calculations, or recursive functions that take too long to complete.
  • Heavy Database Operations: Large joins, complex aggregations, or queries on unindexed tables.
  • External API Calls: Waiting for responses from third-party services that are slow or unresponsive.
  • File Operations: Processing large files, image manipulation, or extensive file I/O.
  • Large Data Imports/Exports: Scripts designed to handle significant data transfers without proper chunking or background processing.
  • Infinite Loops: While rare, a programming error could cause a script to loop indefinitely.
  • Resource Constraints: The server itself might be overloaded, causing scripts to run slower than usual and hit the timeout.

Step-by-Step Resolution

Addressing this error requires a multi-pronged approach: first, investigate and optimize the code, and then, if necessary, adjust server-side timeouts.

1. Analyze Your PHP Script and Application Logs

Before increasing timeouts, understand why your script is taking so long. Indiscriminately increasing limits can mask deeper performance issues and potentially lead to server resource exhaustion.

  • Check Application-Specific Logs: Many frameworks (Laravel, Symfony, WordPress) have their own logging mechanisms. These might reveal the specific part of your code that’s causing the delay.
  • Profile Your Code: Use tools like Xdebug or Blackfire to get a detailed breakdown of function execution times and memory usage.
  • Add Debugging Statements: Temporarily add error_log() calls at critical points in your script to pinpoint slow sections.
<?php
error_log("Script started at " . date('Y-m-d H:i:s'));

// Simulate a long operation
sleep(10); // Example: database query or API call

error_log("Operation 1 completed at " . date('Y-m-d H:i:s'));

// Simulate another long operation
sleep(25);

error_log("Operation 2 completed at " . date('Y-m-d H:i:s'));

// This part might not be reached if it times out
?>

2. Increase max_execution_time in php.ini

This is the most common PHP-level adjustment.

  1. Locate your php.ini file: For PHP-FPM, it’s typically found in /etc/php/X.x/fpm/php.ini, where X.x is your PHP version (e.g., 8.1, 8.2). If you’re using mod_php with Apache, it might be in /etc/php/X.x/apache2/php.ini.

    # For PHP-FPM
    sudo nano /etc/php/8.1/fpm/php.ini
    
    # For Apache mod_php
    sudo nano /etc/php/8.1/apache2/php.ini
  2. Find and modify the max_execution_time directive: Change its value to a more suitable limit, for example, 300 seconds (5 minutes).

    ; Maximum execution time of each script, in seconds
    ; http://php.net/max-execution-time
    max_execution_time = 300

    [!IMPORTANT] While increasing this value can resolve the immediate timeout, setting it excessively high (e.g., 0 for unlimited) can be dangerous. It allows runaway scripts to consume all server resources, potentially crashing your server. Only increase it as much as genuinely needed after optimizing your code.

  3. Save the file and restart PHP-FPM or Apache: For PHP-FPM:

    sudo systemctl restart php8.1-fpm

    (Adjust php8.1-fpm to your specific PHP-FPM service name, e.g., php7.4-fpm).

    For Apache mod_php:

    sudo systemctl restart apache2

3. Adjust request_terminate_timeout for PHP-FPM

If you are using PHP-FPM (common with Nginx and Apache’s mod_proxy_fcgi), this directive can override max_execution_time for FastCGI requests.

  1. Locate your PHP-FPM pool configuration file: This is usually /etc/php/X.x/fpm/pool.d/www.conf (or another pool file if you have custom pools).

    sudo nano /etc/php/8.1/fpm/pool.d/www.conf
  2. Find and modify the request_terminate_timeout directive: Set it to the same or a slightly higher value than max_execution_time. A value of 0 means it will respect max_execution_time. We’ll set it explicitly to 300s for consistency.

    ; The timeout for serving a single request after which the worker process will
    ; be killed. This option should be used when the 'max_execution_time' PHP
    ; configuration option does not work as expected for some reason.
    ; If set to 0, 'max_execution_time' will be used instead.
    request_terminate_timeout = 300
  3. Save the file and restart PHP-FPM:

    sudo systemctl restart php8.1-fpm

4. Configure fastcgi_read_timeout in Nginx

If you’re using Nginx as your web server, it needs to wait long enough for PHP-FPM to respond.

  1. Locate your Nginx site configuration file: This is typically found in /etc/nginx/sites-available/yourdomain.conf.

    sudo nano /etc/nginx/sites-available/yourdomain.conf
  2. Add or modify the fastcgi_read_timeout directive: Place this directive inside the location ~ \.php$ block. Set it to a value equal to or greater than your max_execution_time and request_terminate_timeout.

    server {
        listen 80;
        server_name yourdomain.com;
        root /var/www/html/your-app;
        index index.php index.html index.htm;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
            fastcgi_read_timeout 300s; # <--- Add or modify this line
        }
    
        # ... other configurations ...
    }

    [!WARNING] Setting fastcgi_read_timeout to an extremely high value without corresponding PHP-FPM timeouts can leave worker processes waiting indefinitely for a broken PHP script. Ensure your PHP timeouts are aligned or shorter.

  3. Test Nginx configuration and reload:

    sudo nginx -t
    sudo systemctl reload nginx

5. Adjust Timeout in Apache (if applicable)

If you are using Apache with mod_php or mod_proxy_fcgi, you might need to adjust Apache’s Timeout directive.

  1. Locate your Apache configuration file: This can be httpd.conf, apache2.conf, or a specific virtual host file (e.g., /etc/apache2/sites-available/yourdomain.conf).

    sudo nano /etc/apache2/apache2.conf
    # OR
    sudo nano /etc/apache2/sites-available/yourdomain.conf
  2. Find and modify the Timeout directive: Its default is usually 300 seconds. Ensure it’s sufficient for your long-running scripts.

    # Timeout: The number of seconds before receives and sends time out.
    Timeout 300
  3. Save the file and restart Apache:

    sudo systemctl restart apache2

6. Optimize PHP Code and Database Queries

This is the most critical and sustainable long-term solution. Increasing timeouts is a workaround, not a fix for inefficient code.

  • Database Optimization:

    • Add indexes to frequently queried columns.
    • Rewrite complex queries to be more efficient.
    • Use EXPLAIN or database profiling tools to identify slow queries.
    • Fetch only necessary columns, not SELECT *.
    • Implement caching for frequently accessed data.
  • Code Efficiency:

    • Avoid N+1 queries.
    • Refactor inefficient loops and algorithms.
    • Stream large file operations instead of loading entire files into memory.
    • Cache results of expensive computations.
  • Temporarily Bypass Timeouts (with extreme caution): For very specific, well-understood, non-user-facing scripts (e.g., CLI cron jobs), you can use set_time_limit(0) at the beginning of your PHP script to disable the max_execution_time limit.

    <?php
    set_time_limit(0); // Disable execution time limit for this script only
    
    // Long-running code
    ?>

    [!WARNING] Using set_time_limit(0) for web-facing scripts is highly discouraged. A bug in your script could cause it to run indefinitely, consuming all server resources and potentially crashing your server. It’s only suitable for controlled, background processes.

7. Consider Asynchronous Processing / Background Jobs

For truly long-running tasks (e.g., video encoding, large data imports, sending thousands of emails), it’s best practice to decouple them from the web request cycle.

  • Message Queues: Implement a message queue system (e.g., RabbitMQ, Redis Queue, AWS SQS) to push long-running tasks to a queue.
  • Workers: Create worker processes (PHP scripts running in the background, managed by Supervisor, systemd, or a framework’s queue worker) that pull tasks from the queue and process them.
  • User Feedback: The web interface can immediately acknowledge the request and notify the user that the task is being processed, perhaps updating the status via websockets or polling.

8. Docker/Containerized Environments

If your application runs in Docker containers, the php.ini and PHP-FPM pool configuration files are typically inside the container.

  1. Access the Container:
    docker exec -it <container_id_or_name> /bin/bash
  2. Locate Configuration: The paths (/etc/php/X.x/fpm/php.ini, /etc/php/X.x/fpm/pool.d/www.conf) will be relative to the container’s filesystem.
  3. Modify and Restart: You can either modify them directly within the container (not recommended for production as changes are lost on rebuild/restart) or, preferably:
    • Mount Custom Configs: Mount custom php.ini or pool files from your host machine into the container using docker-compose.yml or docker run -v.
    • Dockerfile: Build a custom Docker image that copies your modified php.ini during the build process.
    FROM php:8.1-fpm-alpine
    
    COPY custom-php.ini /usr/local/etc/php/php.ini
    COPY custom-www.conf /usr/local/etc/php-fpm.d/www.conf
    
    # ... rest of your Dockerfile
  4. Restart the Container:
    docker restart <container_id_or_name>

By following these steps, you’ll be able to effectively diagnose and resolve PHP maximum execution time exceeded errors, leading to a more robust and performant web application.