Runtimes Advanced

Troubleshooting PHP Maximum Execution Time Exceeded on Alpine Linux (php-fpm, Nginx)

Fix 'PHP maximum execution time of 30 seconds exceeded' on Alpine Linux. Learn to adjust PHP-FPM, Nginx, and system-level timeouts for long-running scripts.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Fix 'PHP maximum execution time of 30 seconds exceeded' on Alpine Linux. Learn to adjust PHP-FPM, Nginx, and system-level timeouts for long-running scripts.

Welcome to this in-depth guide for resolving the frustrating "PHP maximum execution time of 30 seconds exceeded" error, specifically tailored for environments running on Alpine Linux with PHP-FPM and Nginx. This common issue occurs when a PHP script takes longer to execute than the predefined limit, causing the web server to terminate the request prematurely. Understanding and correctly configuring the various timeout parameters across PHP, PHP-FPM, and Nginx is crucial for stable and performant web applications, especially those requiring longer processing times.

Symptom & Error Signature

When a PHP script exceeds its maximum execution time, users typically encounter a blank page, a generic "500 Internal Server Error," or a "504 Gateway Timeout" in their browser. The precise error messages detailing the timeout will be logged in various system and application log files.

Here are the typical log entries you might find:

PHP-FPM Error Log (e.g., /var/log/phpX/error.log or stderr if running in Docker):

[26-Oct-2023 10:00:30 UTC] WARNING: [pool www] child 1234 exited with code 0 after 30.123456 seconds from start
[26-Oct-2023 10:00:30 UTC] NOTICE: [pool www] 'child 1234' process will be respawned
[26-Oct-2023 10:00:30 UTC] WARNING: [pool www] script '/path/to/your/long_script.php' (request_uri: /long_script.php) execution timed out (30.000 seconds), terminating

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

2023/10/26 10:00:35 [error] 1234#1234: *5 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.100, server: example.com, request: "GET /long_script.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock:", host: "example.com"

Root Cause Analysis

The "maximum execution time exceeded" error is a multi-layered issue involving various components of your web serving stack, each with its own timeout mechanisms. Understanding these layers is key to a complete resolution:

  1. PHP's max_execution_time: This is the primary limit imposed by PHP itself. It dictates how long a single PHP script is allowed to run. By default, it's often set to 30 or 60 seconds. When this limit is hit, PHP will attempt to terminate the script, logging the PHP Fatal error: Maximum execution time... message.

  2. PHP-FPM's request_terminate_timeout: PHP-FPM (FastCGI Process Manager) is the intermediary between Nginx and PHP. Its request_terminate_timeout directive in the FPM pool configuration (e.g., www.conf) controls how long the FPM master process will wait for a child process to finish processing a request before forcefully killing it. If this is set lower than or equal to PHP's max_execution_time, it can prematurely terminate scripts.

  3. Web Server (Nginx) Upstream Timeouts: Nginx, acting as a reverse proxy to PHP-FPM, has its own set of timeouts for FastCGI communication (fastcgi_read_timeout, fastcgi_send_timeout, fastcgi_connect_timeout). If Nginx doesn't receive a response from PHP-FPM within these limits, it will terminate the connection, leading to an Nginx-level timeout error (e.g., upstream timed out). This often manifests as a "504 Gateway Timeout" to the user.

  4. Application-Specific Latency: The most common reason for hitting these limits is that a PHP script genuinely takes a long time. This could be due to:

    • Inefficient Code: Unoptimized loops, complex data processing, or recursive functions.
    • External Dependencies: Waiting for slow database queries, API calls to external services, or file system operations over a network.
    • Large Data Processing: Importing/exporting large files, image manipulation, or complex calculations.
  5. Reverse Proxy/Load Balancer Timeouts: If your application sits behind an additional layer like a cloud load balancer (e.g., AWS ALB/ELB), Cloudflare, or another reverse proxy, they often have their own default timeouts (e.g., 60 seconds). If all underlying timeouts are increased but this layer still terminates, the issue will persist.

Step-by-Step Resolution

To effectively resolve this issue, you need to adjust timeouts across all involved components. It's crucial to address them in a cascading manner, ensuring each layer allows for at least as much time as the preceding one, with PHP's max_execution_time being the absolute minimum for the script itself.

1. Identify the Culprit Script and Duration

Before arbitrarily increasing timeouts, try to determine which script is timing out and approximately how long it takes.

  • Check logs: The PHP-FPM error logs will often specify the script path and the exact duration before termination.
  • Profile: If possible, use profiling tools like Xdebug or Blackfire to analyze the script's execution path and identify bottlenecks.

2. Increase PHP's max_execution_time

This is the most direct PHP configuration for script execution limits.

  • Locate php.ini: On Alpine Linux, PHP configuration files are typically found under /etc/phpX/, where X denotes the PHP version (e.g., php81). The primary configuration file is usually /etc/phpX/php.ini. Alternatively, custom settings can be placed in .ini files in the /etc/phpX/conf.d/ directory (e.g., 99-custom.ini).

    # For PHP 8.1 example
    vi /etc/php81/php.ini
    
  • Modify max_execution_time: Find the line max_execution_time and set it to a higher value. A common starting point for longer tasks is 120 or 300 seconds. For truly indefinite background tasks, consider 0 (which means no limit, but use with extreme caution and only if request_terminate_timeout is also managed).

    ; Maximum execution time of each script, in seconds
    ; https://php.net/max-execution-time
    max_execution_time = 300
    
  • Restart PHP-FPM: After modifying php.ini, you must restart the PHP-FPM service for changes to take effect. On Alpine Linux, which typically uses OpenRC as its init system:

    rc-service php-fpm81 restart
    

    (Adjust php-fpm81 to your PHP version, e.g., php-fpm74, php-fpm82).

    If you're running PHP-FPM in a Docker container, you'll need to modify the php.ini within the container or via a custom Dockerfile layer. Then, restart the container:

    # Example for modifying inside a running container (temporary for testing)
    docker exec -it <container_name_or_id> vi /etc/phpX/php.ini
    # Then restart php-fpm inside container (if it's not PID 1) or restart the container
    docker restart <container_name_or_id>
    
    # For persistent changes, prefer updating your Dockerfile:
    # COPY my-custom-php.ini /etc/phpX/conf.d/
    # Then rebuild and redeploy your container.
    

3. Adjust PHP-FPM request_terminate_timeout

This setting prevents rogue PHP-FPM child processes from running indefinitely. It should ideally be set greater than max_execution_time.

  • Locate PHP-FPM pool configuration: On Alpine, PHP-FPM pool configurations are typically found in /etc/phpX/php-fpm.d/www.conf.

    vi /etc/php81/php-fpm.d/www.conf
    
  • Modify request_terminate_timeout: Find the line starting with request_terminate_timeout. Set it to a value slightly higher than your max_execution_time. If max_execution_time is 300, set this to 310 or 320. Setting it to 0 also disables the timeout for PHP-FPM (use with caution, similar to max_execution_time = 0).

    ; 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' ini option
    ; does not stop script execution for some reason. A value of 0 means 'off'.
    ; Available units: s(econds)(default), m(inutes), h(ours), d(ays)
    request_terminate_timeout = 320s
    
  • Restart PHP-FPM: Apply the changes by restarting PHP-FPM.

    rc-service php-fpm81 restart
    

4. Configure Nginx FastCGI Timeouts

Nginx needs to be aware that PHP-FPM might take longer to respond. Adjust its FastCGI timeout parameters.

  • Locate Nginx virtual host configuration: Nginx configurations on Alpine Linux are often in /etc/nginx/http.d/default.conf or a custom file like /etc/nginx/conf.d/my_app.conf.

    vi /etc/nginx/http.d/default.conf
    
  • Add/Adjust fastcgi_*_timeout directives: Inside your location ~ .php$ block, add or modify the following directives. Set them to be greater than or equal to your request_terminate_timeout value.

    location ~ .php$ {
        root           /var/www/localhost/htdocs; # Adjust to your web root
        fastcgi_pass   unix:/run/php-fpm/php-fpm81.sock; # Adjust to your PHP-FPM socket path
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    
        # Increase FastCGI timeouts
        fastcgi_read_timeout 330s;
        fastcgi_send_timeout 330s;
        fastcgi_connect_timeout 330s;
    }
    
    • fastcgi_read_timeout: Timeout for reading a response from the FastCGI server (PHP-FPM).
    • fastcgi_send_timeout: Timeout for transmitting a request to the FastCGI server.
    • fastcgi_connect_timeout: Timeout for establishing a connection with the FastCGI server.
  • Test Nginx configuration and reload: Always test Nginx configuration before reloading or restarting to avoid downtime.

    nginx -t
    

    If the test is successful, reload Nginx:

    rc-service nginx reload
    

    If Nginx is running in a Docker container, modify the Nginx configuration within the container or, preferably, via a custom Dockerfile layer. Then restart the container.

5. Consider Application-Level Timeouts (Use with Caution)

For very specific, long-running scripts, you can override max_execution_time directly within the PHP script itself.

<?php
// Set execution time to 5 minutes (300 seconds) for this specific script
set_time_limit(300);

// For an indefinite execution time (no limit)
// set_time_limit(0);

// Your long-running script logic
// ...
?>

Using set_time_limit(0) should be done with extreme caution. It removes the PHP-level safety net, making it possible for runaway scripts to consume excessive resources and potentially destabilize your server. Only use it for well-tested, controlled background processes, and ensure request_terminate_timeout in PHP-FPM or Nginx upstream timeouts are still in place to provide a system-level fail-safe.

6. Optimize the PHP Script (Long-Term Solution)

While increasing timeouts provides an immediate fix, it's often a band-aid solution. The best long-term approach is to optimize the PHP script itself to reduce its execution time.

  • Database Query Optimization:

    • Add appropriate indexes to frequently queried columns.
    • Refactor complex queries to be more efficient.
    • Avoid N+1 query problems.
    • Use pagination for large result sets.
  • Caching:

    • Implement object caching (e.g., Redis, Memcached) for frequently accessed data.
    • Use opcache for PHP bytecode caching.
    • Implement full-page caching for static content.
  • Asynchronous Processing:

    • For tasks that don't require an immediate response (e.g., sending emails, generating reports, processing images), offload them to a message queue (e.g., RabbitMQ, Redis Queue) and process them with background workers (e.g., Supervisord, systemd services, or Kubernetes Jobs).
    • On Alpine, you can install Supervisord with apk add supervisor and configure it to manage background PHP workers.
  • Code Refactoring:

    • Break down large functions into smaller, manageable units.
    • Process large data sets in chunks rather than all at once.
    • Reduce redundant computations.
  • Profiling:

    • Continuously use tools like Xdebug or Blackfire to profile your application and identify performance bottlenecks.

Optimizing your code is the most robust and scalable solution. Increasing timeouts without addressing underlying inefficiencies only postpones the problem and can lead to resource exhaustion on your server.

By systematically adjusting these configurations and, crucially, optimizing your application code, you can effectively resolve the "PHP maximum execution time of 30 seconds exceeded" error on your Alpine Linux setup.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.