Optimizing the performance of 1C-Bitrix agents

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Optimizing 1C-Bitrix Agent Performance

Bitrix Agent Optimization: Diagnosing and Configuring Background Tasks

Agents in Bitrix are PHP functions that the platform executes on a schedule. This sounds straightforward until you discover that the site slows down every 30 seconds, all pages take an extra 500–800 ms to respond precisely when agents are triggered, and the b_agent table has accumulated 400+ records — half of them stuck tasks with ACTIVE = Y and NEXT_EXEC in the past.

The standard agent execution model via web requests (hitAgent) is an architectural compromise in Bitrix that works acceptably on small sites but becomes a serious problem on high-traffic projects. Any incoming HTTP request can become a "victim" on which agent execution is piggy-backed, blocking the user response for the duration of the background task.

Diagnosing the Current State

The first step is to look at the real picture in the agents table:

SELECT NAME, ACTIVE, NEXT_EXEC, LAST_EXEC,
       TIMESTAMPDIFF(MINUTE, LAST_EXEC, NOW()) AS minutes_since_last
FROM b_agent
WHERE ACTIVE = 'Y'
ORDER BY NEXT_EXEC ASC;

Agents with NEXT_EXEC several hours or days in the past are stuck tasks. They constantly attempt to run, occupy an execution slot, and block other agents in the queue.

The second step is to examine the execution time of heavy agents. If the search agent (CSearchIndex::IndexAgent) takes 45 seconds while configured to run every minute — it never completes correctly and is restarted before the previous instance finishes.

The third step is to profile the impact of agents on page response times. Enable the Bitrix debug panel or log timing via \Bitrix\Main\Diag\Debug::startTimeLabel / stopTimeLabel in init.php.

Switching Agents to Cron

This is the most important change. In /bitrix/.settings.php or via the admin interface (Settings → Performance):

'agents' => [
    'value' => [
        'pull_agent_manager' => 'cron',
    ],
],

Add to crontab:

*/1 * * * * /usr/bin/php -f /var/www/bitrix/bitrix/modules/main/tools/cron_events.php > /dev/null 2>&1

After switching to cron, agents no longer execute in the context of web requests. Page response times stabilize, and the characteristic latency spikes every N seconds disappear from the graphs.

An important nuance: the CSearchIndex::IndexAgent search agent running via cron may compete with PHP-FPM for CPU. Move it to a separate cron script with nice -n 10 and a runtime limit using timeout.

Queue and Priority Optimization

After switching to cron, address the accumulated backlog:

Cleaning up stuck agents. Agents with NEXT_EXEC older than a day and no successful LAST_EXEC in the last 48 hours are candidates for deactivation or recreation. For each one, investigate: is the module alive? Does the function exist? Are there exceptions in the logs?

Optimizing intervals. CSearchIndex::IndexAgent with a 30-second interval when actual execution time is 20 seconds is a recipe for disaster. Recalculate intervals based on real execution time plus a 50% buffer.

Spreading heavy agents. If several heavy agents (1C synchronization, email newsletter sending, price recalculation) are scheduled to run simultaneously — spread their start times via NEXT_EXEC with 5–10 minute intervals.

Execution monitoring. Add logging to custom agents:

function MyHeavyAgent(): string
{
    $start = microtime(true);
    // ... logic ...
    $elapsed = microtime(true) - $start;
    if ($elapsed > 10) {
        \Bitrix\Main\Diag\Debug::writeToFile(
            "MyHeavyAgent took {$elapsed}s",
            '',
            '/bitrix/logs/agent_performance.log'
        );
    }
    return 'MyHeavyAgent();';
}

Heavy System Agents: What to Do with Them

CSearchIndex::IndexAgent — search indexing. On a catalog of 50,000+ products it can run for hours. Solution: limit the number of elements per run via the SEARCH_ELEMENT_COUNT parameter in the search module settings, or migrate to Elasticsearch and disable the built-in search.

CEventMessageAgent — email sending. If the built-in Bitrix mail system is used without a queue — when thousands of messages accumulate, the agent hangs. Solution: configure SMTP via a PHPMailer-compatible transport or switch to Unisender/SendPulse API with a queue.

CBitrixCloudBackupAgent — cloud backup. Can consume all server I/O with large volumes. Move to nighttime execution and add speed limiting via ionice.

CTaskNotifications::agent (Bitrix24) — CRM notifications. Runs for a long time under high task volumes. Split into batches using a limit parameter in the agent body.

Setting Up Agent Monitoring

Add a stuck-agent count metric to Zabbix/Prometheus:

SELECT COUNT(*) as stuck_agents
FROM b_agent
WHERE ACTIVE = 'Y'
  AND NEXT_EXEC < DATE_SUB(NOW(), INTERVAL 1 HOUR);

If the value is > 0 for more than 30 minutes — trigger an alert in Telegram/Slack. This is an early indicator of cron issues or server overload.

Result

Switching to cron and optimizing the agent queue eliminates periodic response time spikes, reduces database load during peak moments by 20–40%, and ensures predictable background task execution without impacting user-facing requests.