⏱️
Hosting

max_execution_time: handling long-running PHP scripts

11.11.2026
← All articles

An import script, a report page or a backup plugin runs for a while and then stops with Fatal error: Maximum execution time of 30 seconds exceeded. That is PHP's max_execution_time, which caps how long a single script may run and defaults to 30 seconds. Here is how it is counted, when raising it makes sense and when the task itself should be restructured.

How the limit is counted

On Linux it is not wall-clock time. According to the PHP manual, only the script's own execution counts; waiting for database queries, stream operations, sleep() and commands run via system() are excluded. On Windows real elapsed time is measured. Scripts run from the command line (CLI) default to 0, meaning no time limit, which is why cron jobs are far more reliable than browser-triggered pages.

PHP error vs 504 Gateway Timeout

If the log says "Maximum execution time", PHP stopped the script. If the browser shows 504 Gateway Timeout and the PHP log is empty, the web server in front of PHP gave up waiting. In Nginx that is fastcgi_read_timeout or proxy_read_timeout (60 seconds by default), and PHP-FPM can also kill a request via request_terminate_timeout. On shared hosting these are not customer settings, so a 300-second max_execution_time may still end in a 504 after 60 seconds.

Raising the limit

For tasks that need a bit more than 30 seconds, change max_execution_time in the PHP settings of the hosting panel (ISPmanager, opened from the sayt.uz cabinet), or use .user.ini under FPM/CGI. php_value in .htaccess works only with mod_php.

; .user.ini
max_execution_time = 120

In code, set_time_limit() restarts the counter from zero each time it is called, so calling it inside a loop effectively removes the limit. Handy, but a buggy loop will then run forever:

foreach ($rows as $row) {
    importRow($row);
    set_time_limit(30);
}

The related max_input_time limits time spent receiving and parsing request input, which matters for large uploads over slow connections.

Move heavy work out of the browser

A task that takes minutes should not run through a web page: a closed tab or a server timeout leaves data half-written. Run it from the CLI via cron instead; ISPmanager has a section for scheduled jobs:

30 3 * * * /usr/bin/php /var/www/example_user/data/www/example.uz/cron/import.php >> /var/www/example_user/data/logs/import.log 2>&1

PHP and folder paths vary by server and PHP version, so confirm them in the panel or with support, and always log the output. If the task must start from a button, split it into batches: each request processes, say, 200 records, saves its position, and JavaScript fires the next request while showing progress.

Example: a wholesaler in Namangan

A building materials wholesaler in Namangan updates prices on misol.uz daily from an XML export. Clicking "Import" in the admin area failed halfway through an 8,000-product file, leaving half the prices new and half old. The developer rewrote the import for CLI, scheduled it in cron at 06:00 and logged progress every 500 products. The import no longer depends on the time limit.

Choosing a fix

A huge limit only hides the problem: a slow script keeps holding server resources, and if several users start it at the same time the whole site slows down. So first check why the task is slow, for example queries without indexes, unnecessary external API calls or processing the same data twice.

Related articles

🥟 Bun Instead of Node.js? When It Works and How to Run It on a Server 📦 Telegram Bot API Local Server: Running Your Own for Large Files 💻 VS Code Remote SSH: editing code directly on your server 🚦 MySQL "Too many connections" Error: Causes and Fixes
🌐 Language
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English ✓