Setup of deferred functions 1C-Bitrix
User clicks "Checkout" — and waits 4 seconds while the server sends email, calculates bonuses, calls delivery API, and writes logs. All this happens synchronously in OnSaleOrderBeforeSaved event handlers. Deferred functions allow moving heavy operations out of the main thread: the response goes to user immediately, and background tasks execute after HTTP response is sent.
How it works
Starting with PHP 8.1, Bitrix core supports register_shutdown_function and own deferred execution mechanism via Bitrix\Main\Application::getInstance()->addBackgroundJob(). Essence: a function is registered in a queue that executes after fastcgi_finish_request() (for PHP-FPM) or after response is sent (for Apache mod_php via register_shutdown_function).
use Bitrix\Main\Application;
Application::getInstance()->addBackgroundJob(function () {
// This code runs AFTER response is sent to client
\Bitrix\Main\Mail\Event::send([...]);
// Logging, API calls, data recalculation
});
Critical nuance: addBackgroundJob works only when fastcgi_finish_request() exists. If PHP runs as Apache module (mod_php) — function executes before response is sent, because register_shutdown_function doesn't release connection. Check: function_exists('fastcgi_finish_request').
When to use
- Sending email/SMS after order checkout — 200–500 ms delay per message
- Logging — write to file or external service (ELK, Sentry)
- Cache invalidation — rebuild tagged cache after catalog update
- External API calls — notify CRM, update warehouse service
- Search index updates — reindex element after change
Limitations
- No execution guarantee: if PHP process crashes (OOM, kill) — task is lost. For critical operations (payment, document creation) use task queue, not deferred functions.
- No retries: if API returns error — no retry handling.
- No monitoring: can't know how many tasks in queue and how many executed.
- Execution order — FIFO within one request, but between requests — not guaranteed.
PHP-FPM configuration
For correct deferred function work on PHP-FPM check:
-
request_terminate_timeoutin FPM pool — must be enough to complete background tasks (default — 0, unlimited). If set to 30 seconds and background task runs 40 — process will be killed. -
pm.max_children— each request with background tasks holds worker longer. High traffic can exhaust pool.
What we configure
- Check server environment compatibility (PHP-FPM,
fastcgi_finish_request) - Move heavy event handlers to
addBackgroundJob - Configure
request_terminate_timeoutin PHP-FPM - Monitoring: log background task execution time
- Testing: measure response time before and after moving operations to deferred







