RabbitMQ for Reliable 1C-Bitrix Integration
At the moment an order is placed, Bitrix fires an event handler to send data to 1C, CRM, or warehouse. If the external system is down, the user sees an error and the order is lost. We have repeatedly had to restore such orders manually.
Direct exchange via HTTP or CommerceML blocks script execution for the duration of the request. Under a load of 5,000 orders per hour, unstable connections to 1C caused up to 15% of orders to be lost. After implementing RabbitMQ with Dead Letter Queue and retry logic, losses dropped to 0.1%. Processing time was cut by up to 60% thanks to asynchrony, and annual maintenance savings reach $4.5k–6.5k.
The solution: RabbitMQ—Bitrix publishes a message to a queue and does not wait for a reply. A dedicated worker picks up the message and delivers it to the target system, retrying on failure. This approach guarantees delivery and prevents data loss even during temporary outages.
Why RabbitMQ is Better Than Direct Integrations?
A direct synchronous HTTP call to an external system blocks the Bitrix event handler: the user waits for a response, and on error, data is permanently lost. RabbitMQ is asynchronous—the message is stored in a queue and will be processed even if the external system is temporarily unavailable. Delivery reliability: synchronous exchange loses up to 5% of events, with RabbitMQ—less than 0.1%.
| Criterion | Synchronous Exchange | RabbitMQ |
|---|---|---|
| Reliability | Depends on external system availability | Guaranteed delivery (ack, DLQ)—10x more reliable |
| Performance | Blocks handler until response (up to 5 sec) | Asynchronous, instant return (< 1 ms) |
| Scalability | Limited to one call | Workers can be scaled horizontally |
| Error Handling | Manual recovery | Automatic retry |
How RabbitMQ Solves Data Loss
With synchronous exchange, a failure in the external system leads to event loss. RabbitMQ stores the message until the worker confirms its processing (ack). If a worker crashes, the message remains in the queue and is processed by another process. Dead Letter Queue (DLQ) isolates "problematic" messages for manual review.
Messages with delivery_mode = 2 (Persistent) are saved to disk and guaranteed to be delivered even after broker restart. For extra reliability, we use Publisher Confirms: the producer receives confirmation that the broker has accepted the message. This is standard practice for highload systems.
Publishing Messages from Bitrix
To work with RabbitMQ from PHP, use the php-amqplib library. Install via Composer in /local/: composer require php-amqplib/php-amqplib.
Publisher class:
use PhpAmqpLib\Connection\AMQPStreamConnection; use PhpAmqpLib\Message\AMQPMessage; class RabbitMQPublisher { private static ?AMQPStreamConnection $connection = null; private static function getConnection(): AMQPStreamConnection { if (!self::$connection || !self::$connection->isConnected()) { self::$connection = new AMQPStreamConnection( COption::GetOptionString('site', 'rmq_host', 'localhost'), COption::GetOptionInt('site', 'rmq_port', 5672), COption::GetOptionString('site', 'rmq_user', 'guest'), COption::GetOptionString('site', 'rmq_pass', 'guest'), COption::GetOptionString('site', 'rmq_vhost', '/') ); } return self::$connection; } public static function publish(string $exchange, string $routingKey, array $payload): void { $channel = self::getConnection()->channel(); $channel->exchange_declare($exchange, 'topic', false, true, false); $msg = new AMQPMessage( json_encode($payload), ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT, 'content_type' => 'application/json'] ); $channel->basic_publish($msg, $exchange, $routingKey); $channel->close(); } } Publishing on Bitrix Events
// In init.php AddEventHandler('sale', 'OnSaleOrderSaved', function($order) { if ($order->isNew()) { RabbitMQPublisher::publish('bitrix.events', 'order.created', [ 'order_id' => $order->getId(), 'user_id' => $order->getUserId(), 'total' => $order->getPrice(), 'timestamp' => time(), ]); } }); AddEventHandler('catalog', 'OnAfterIBlockElementAdd', function($fields) { RabbitMQPublisher::publish('bitrix.events', 'product.created', [ 'element_id' => $fields['ID'], 'iblock_id' => $fields['IBLOCK_ID'], 'name' => $fields['NAME'], ]); }); How to Set Up a Worker Consumer?
- Install the php-amqplib library via Composer.
- Create a worker file, e.g.
/local/workers/order_worker.php:
// worker.php require '/local/vendor/autoload.php'; require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php'; $connection = new AMQPStreamConnection(/* parameters */); $channel = $connection->channel(); $channel->queue_declare('order.processor', false, true, false, false); $channel->queue_bind('order.processor', 'bitrix.events', 'order.created'); $channel->basic_qos(null, 5, null); $channel->basic_consume('order.processor', '', false, false, false, false, function($msg) { $data = json_decode($msg->getBody(), true); try { OrderSyncHandler::process($data); $msg->ack(); } catch (\Throwable $e) { $msg->nack(false, true); } } ); while ($channel->is_consuming()) { $channel->wait(); } - Configure Supervisor for automatic restarts:
[program:bitrix_order_worker] command=php /var/www/bitrix.loc/local/workers/order_worker.php numprocs=3 autostart=true autorestart=true stderr_logfile=/var/log/supervisor/bitrix_worker.err.log Dead Letter Queue: Handling Unprocessed Messages
Messages that fail after N attempts are moved to DLQ for manual review. Configure when declaring the queue:
$channel->queue_declare('order.processor', false, true, false, false, false, [ 'x-dead-letter-exchange' => ['S', 'bitrix.dlx'], 'x-dead-letter-routing-key' => ['S', 'order.failed'], 'x-message-ttl' => ['I', 3600000], // 1 hour TTL ]); Monitor DLQ via RabbitMQ Management UI (port 15672) or through alerts on queue growth. In practice, DLQ contains less than 0.5% of messages, enabling quick detection of systemic errors.
Common Problems and Solutions
| Error | Consequence | Solution |
|---|---|---|
| Worker without Supervisor | Does not restart on crash—queue grows | Supervisor with autorestart |
| No DLQ configured | Problematic messages block the queue | Set x-dead-letter-exchange |
| No monitoring | Queue growth goes unnoticed | Grafana + RabbitMQ Management |
| Wrong exchange type | Messages not routed | Use topic/direct per task |
What Is Included in RabbitMQ Setup for Bitrix?
We provide turnkey work:
- Audit of current data exchange and architecture.
- Design of queue schema, exchanges, and routing keys.
- Deployment of RabbitMQ (server or cloud), cluster configuration.
- Implementation of publisher classes and workers for your scenarios.
- Configuration of Supervisor for worker management.
- Setup of DLQ and monitoring (alerts, Management UI).
- Documentation of exchange schema and admin instructions.
- Training your team on working with queues.
Estimated Timelines
| Scenario | Duration |
|---|---|
| Simple (one queue, one worker) | 1–2 days |
| Medium (multiple queues, DLQ, 2–3 systems) | 5–10 days |
| Complex (highload, cluster, custom consumers) | 2–4 weeks |
Our Experience
We have been doing Bitrix integrations for over 10 years. We have completed 50+ projects with RabbitMQ, including fintech and retail. We use proven patterns: delivery confirmation, DLQ, monitoring via Management UI and alerts. We guarantee reliable exchange and timely support.
Contact us for an audit of your exchange architecture. Get a free consultation. Order RabbitMQ setup and forget about lost orders.

