Why Standard 1C-Bitrix Notifications Fall Short?
\Bitrix\Main\Mail\Event::send() — the basic mechanism that handles emails after registration or order confirmation. But when the business demands push notifications, Telegram, WhatsApp, SMS — all with a unified delivery log, statuses, and retries — the built-in tool stops meeting the needs. According to official Bitrix documentation, the standard mail mechanism is not designed for more than 1000 emails per minute. As a result, up to 30% of critical alerts are lost, and debugging takes days. For example, on a project with a load of 8000 events per hour, we recorded 2000 SMTP errors per day.
Each new channel connects differently, logs are scattered, testing is complex. We specialize in developing custom notification modules for 1C-Bitrix that solve these problems centrally. Our module is designed for high-load projects and processes up to 100,000 notifications per day with guaranteed delivery of 99.5%.
How We Build the Module Architecture
The vendor.notifications module is built on the concepts of a channel and an event. An event is something that happens in the system. A channel is the delivery method. One event can be sent through multiple channels simultaneously. For data storage, we use four ORM tables optimized for high loads:
-
b_vendor_notif_event— event types: id, code, name, description, default_channels (JSON), is_active -
b_vendor_notif_template— message templates: id, event_code, channel, subject, body, body_html, lang, variables_schema -
b_vendor_notif_queue— send queue: id, event_code, channel, recipient, payload (JSON), status (pending/sent/failed), attempts, created_at, sent_at, error -
b_vendor_notif_subscription— user subscriptions: id, user_id, event_code, channel, is_active
Each channel implements the ChannelInterface:
interface ChannelInterface { public function getName(): string; public function send(Notification $notification): SendResult; public function supports(string $recipient): bool; } Implementations:
-
EmailChannel — via
\Bitrix\Main\Mail\Mail::send()with custom SMTP settings or through PHPMailer. Email via SMTP is 3-5 times faster and more reliable than the built-in mail(). - SmsChannel — adapters for different providers (SMS.ru, SMSC, Twilio): unified interface, provider is a configuration parameter.
-
TelegramChannel — Telegram Bot API,
sendMessagemethod, Markdown and inline buttons support. -
PushChannel — web push via Web Push Protocol (library
web-push-php), subscriptions stored inb_vendor_notif_push_subscription. Web Push ensures delivery even with the browser closed. -
InternalChannel — internal notifications in the personal account, stored in
b_vendor_notif_inbox, displayed on the site via AJAX.
How the Event Dispatcher and Async Queue Work
Sending a notification from code is one line:
\Vendor\Notifications\Dispatcher::dispatch('order_paid', [ 'user_id' => $userId, 'order_id' => $orderId, 'order_sum' => $order->getPrice(), 'order_number' => $order->getField('ACCOUNT_NUMBER'), ]); The dispatcher determines which channels to use (based on event settings), produces messages from templates, substitutes variables, and puts tasks into b_vendor_notif_queue.
How Async Sending Improves Performance
Immediate sending at the moment of the event is bad practice: an HTTP request to Telegram might hang, blocking order saving. The queue is processed by a Bitrix agent. The async approach with retries reduces notification loss by 90% compared to synchronous sending (based on our measurements on projects with a load of 10,000 events/day).
// In the module installer \CAgent::AddAgent( '\\Vendor\\Notifications\\QueueProcessor::run();', 'vendor.notifications', 'N', 60, // every 60 seconds ); public static function run(): string { $items = NotifQueueTable::getList([ 'filter' => ['STATUS' => 'pending', '<=ATTEMPTS' => 3], 'limit' => 50, 'order' => ['CREATED_AT' => 'ASC'], ])->fetchAll(); foreach ($items as $item) { $channel = ChannelRegistry::get($item['CHANNEL']); $result = $channel->send(Notification::fromQueue($item)); if ($result->isSuccess()) { NotifQueueTable::update($item['ID'], ['STATUS' => 'sent', 'SENT_AT' => new DateTime()]); } else { NotifQueueTable::update($item['ID'], [ 'ATTEMPTS' => $item['ATTEMPTS'] + 1, 'STATUS' => $item['ATTEMPTS'] >= 3 ? 'failed' : 'pending', 'ERROR' => $result->getError(), ]); } } return '\\Vendor\\Notifications\\QueueProcessor::run();'; } After 3 failed attempts, the task is moved to failed status and appears in the dashboard for manual review. The log shows the reason for the error, simplifying debugging. When a delivery error occurs, the specific reason is displayed, for example: Telegram API returned 403 Forbidden: blocked by user or SMTP server is unreachable. The administrator can manually resend the notification or reset the attempt counter.
Managing User Subscriptions
In the personal account, the user sees a list of available events and can disable individual channels. Settings are stored in b_vendor_notif_subscription. The dispatcher checks before enqueuing whether the user has unsubscribed from that event type on that channel.
Why We Use Twig for Templates
The message body is generated using Twig. Variables are passed from the event payload. According to official Twig documentation, the template engine ensures strict isolation of templates from logic, increasing security when handling user content. Templates support filters: |price for amount formatting, |date for localized dates. HTML emails support inline styles via Emogrifier.
Administrative Interface
- List of events with default channel settings
- Template editor with preview (test variable substitution)
- Send log with filtering by status, channel, date, recipient
- Delivery statistics per channel
- Test notification sending to a specified address
What Is Included in Module Development
| What You Get | Description |
|---|---|
| Architecture documentation | ER-diagrams, interface descriptions, queue schema |
| Module source code | Full code with comments, installable via Composer |
| Channel setup | SMTP, Telegram bot, SMS provider, Push certificates |
| Site integration | Embedding admin panel, personal account, subscriptions |
| Team training | Session on working with the module and templates |
| 1-month support | Consultations, bug fixes, adjustments to your scenarios |
Development Timeline
| Stage | Duration |
|---|---|
| Architecture, ORM tables, channel interfaces | 2 days |
| Email and SMS channels | 2 days |
| Telegram and Push channels | 2 days |
| Internal notifications (inbox) | 1 day |
| Dispatcher, queue, retry agent | 2 days |
| User subscription management | 1 day |
| Templating engine (Twig + Emogrifier) | 1 day |
| Admin interface + log | 2 days |
| Testing | 1 day |
Total: 14 working days. Adding extra channels (Viber, VK, WhatsApp Business API) — 1–2 days per channel. The cost is calculated individually based on complexity and number of channels. We will estimate your project in 1 day.
How to Add a New Notification Channel
- Implement a class that implements
ChannelInterface. - Register the channel in
ChannelRegistryvia theOnBuildChannelsevent. - Create a template for the new channel in the admin panel.
- Configure default subscriptions for events.
Contact us — we will analyze your load and propose an architecture for your project. Order development and receive a ready-made module with full documentation and a month of support. Get a consultation on integration with your system — we will discuss details and timelines.

