Why cashback accrual in Bitrix breaks under load
Cashback accrual in Bitrix almost always breaks not on the logic of the rules, but at the moment when an order changes status. While there are dozens of orders a day, the mechanics hold up on manual checks and the manager's "eyes".
As soon as the flow grows and orders start closing in parallel, three typical failures surface: desynchronization of orders and points, double accrual, and stuck transactions.
The most common is desynchronization. The status change event is processed in one process, while the balance is written in the personal account in another, and there is no shared transaction between them.
If a handler crashes or an event from an external system is repeated during this interval, the order is already closed, and the points are either not accrued or accrued twice.
The second failure is double accrual on a repeated call: a retry from the payment module, a manual status edit by the manager, or a repeated synchronization with 1C triggers the rule a second time, because there is no idempotent key per order.
The third is stuck transactions with parallel orders. Two orders from the same user are processed simultaneously, both read the same points balance, both write over it — part of the accruals is lost, and the balance in the account diverges from the data in the accounting system.
The error does not reproduce on a test environment with a single order and surfaces only on real customers.
We break down how this is closed: locks at the order level, idempotent keys, a separate queue for accrual, and reconciliation of points with orders on a schedule.
What correct cashback mechanics deliver
A correctly designed cashback accrual in Bitrix is not a "bonus showcase" but a settlement loop built into checkout.
When the rules (product categories, two-step accrual, exclusions) are described declaratively and calculated on the server side, the customer sees the final benefit right in the cart and does not wait for a recalculation after payment.
This directly affects checkout speed: no extra steps, confirmations, or "we'll clarify later" appear, which means fewer abandoned carts on the final screen.
The second effect is the share of repeat purchases. Points that are accrued predictably and redeemed without surprises work as a return mechanism: the customer comes back because they trust their balance.
If accrual "fluctuates" — sometimes it works, sometimes it doesn't — trust in the program falls faster than the member base grows, and repeat orders do not appear.
Manual balance adjustments are a separate matter. Every manual intervention in the customer account means that a rule failed somewhere: a category was not accounted for, an exclusion did not trigger, data diverged between the order and the invoice.
We build the mechanics so that disputed situations are resolved by logic, not by an operator: transactions are idempotent, reprocessing an order does not double the points, and cancellation and refund correctly reverse the accrual. As a result, support stops being "points accounting."
Accrual stability is also predictability under load. During peak sales, the calculation must not compete for the same data with checkout: operations are separated into steps, heavy recalculations go into background processing, and the balance state remains consistent.
Then the mechanics survive a surge of orders without discrepancies, and the team — without nightly reconciliations.
Product categories and cashback accrual rules
Cashback accrual rules in 1C-Bitrix are built as a set of conditions that are applied to the cart at the moment of order placement.
The base logic is linking a product category to an accrual percentage: the category is defined via binding to catalog sections or to product properties, and the percentage is stored in a separate entity so it can be changed without editing code.
When a customer places an order, the system iterates over the line items, determines the category of each, and accrues cashback according to the corresponding rule.
The key point is rule priority.
If a product falls under several conditions at once (for example, it is in a promotional category and at the same time participates in the general loyalty program), without an explicit firing order a conflict arises: the accrual may be doubled or the wrong percentage may be applied.
Therefore, each rule is assigned a weight, and the system takes the first matching one in descending priority order, ignoring the rest for that line item. This yields a predictable result: accounting and the customer see the same amount.
Product exclusions are handled by a separate mechanism — a list of SKUs or a "does not participate in cashback" property.
The exclusion is checked before categories, so an excluded product will not receive an accrual even if it formally falls into a category with a percentage.
This removes the conflict between promotions and the general program: gift items, products with a fixed discount, or restricted items do not break the calculation.
The behavior on partial returns and cancellations is configured separately — the rule must correctly recalculate the accrual rather than leave a "stuck" cashback.
All of this is configured in the administrative panel without modifying the core, so the rules can be changed to suit marketing tasks without risking platform updates.
Two-step accrual: confirmation and crediting
Two-step accrual separates the moment of placing an order from the moment of confirmation: when an order is created, points are not credited to the customer's account but are placed in reserve.
This is fundamental because an order can be cancelled, payment may fail, and some items may be returned. If cashback is credited immediately, the buyer manages to spend the points before the order is confirmed, and upon cancellation the balance goes negative.
Reserving points solves this: the amount is reserved, visible to the customer as "pending confirmation," but does not participate in payment for new orders.
Crediting after payment is triggered by a change in order status. When payment is confirmed, the handler recalculates cashback based on the actually paid items — taking into account applied discounts, promo codes, and category rules.
It is at this step that points move from reserve into the available balance, and an entry with a reference to the order number appears in the transaction history. This order protects both the customer and the business: accrual always corresponds to money actually received.
A separate scenario is order closure. If payment went through but the order is later cancelled or a return is processed, cashback is recalculated again: the accrued amount is reversed proportionally to the returned items. The reserve is then released without crediting.
It is convenient to keep this logic in event handlers for status changes rather than at the moment of placing the order — that way, any changes to the order after payment are handled correctly and do not leave "hanging" points.
For the customer, the difference is visible in the personal account: two amounts — reserved and available points, with a clear status for each transaction.
This eliminates most support requests of the "I paid but there's no cashback" kind: the person sees that the accrual is awaiting order confirmation rather than being lost.
Comparison of cashback accrual modes
The accrual mode determines at what point the user's balance changes and which events can reverse it. An error at this level does not manifest immediately: points are accrued, the order is placed, and a week later there is a refund — and the balance goes negative.
That is why the mode is chosen not by the convenience of the storefront, but by which events in the order are considered irreversible.
| Mode | When it fits | Limitations |
|---|---|---|
| Immediately at checkout | Simple orders without delivery and post-payment, digital goods, gift certificates | A refund or cancellation requires a reversal: if the user has already spent the points, the balance goes negative and has to be closed manually |
| Two-step accrual | Retail with delivery, where an order goes through several statuses | Explicit triggers are needed at each status transition; when an administrator changes the status manually, accrual may not fire if the handler is not subscribed to that event |
| Deferred by event | Goods with a long return period, services, payment after receipt | The user sees the points with a delay — a separate "pending accrual" counter is needed, otherwise support receives requests asking "where is the cashback" |
Two-step accrual is a compromise: an advance in points at checkout and the remainder after the order is closed. It takes the load off support, but requires both steps to be idempotent: a repeated call of the handler must not accrue points twice.
The deferred mode is more often chosen where a refund is the norm rather than the exception. Points are accrued on the "order closed" or "return period expired" event, and until that moment they do not participate in the discount calculation.
This eliminates the class of errors with a negative balance, but adds a separate entity — deferred cashback — which needs to be shown in the personal account and taken into account in reports.
Mixing modes within a single store is possible, but the boundaries must be explicit: the product category or payment type sets the mode, not the checkout logic. Otherwise, when a new category is added, the accrual behavior becomes unpredictable.
How we implement cashback mechanics
We start with an audit: we look at how discounts, bonus programs, and agreements with customers are already structured in the system, and where manual manager edits intersect with automated rules.
At this stage, it's important to find hidden conflicts — for example, when cashback is credited to an item that has already been sold at a discount, or when a product return does not cancel the credited amount. Without such a review, any new logic breaks existing calculations.
- Audit of current logic. We examine the cart, checkout, payment, and returns: where the total is calculated, which handlers already intervene in it, which rules live in the settings, and which are added in code. We identify the points where we can integrate without modifying the core.
- Rules scheme. We agree on a matrix: product categories and catalog sections participating in crediting, percentage or fixed amount, calculation base (price before or after discount), bonus validity period, and redemption conditions. As a separate block — exceptions: promotional items, made-to-order products, gift certificates.
- Setting up handlers. We tie the calculation to checkout events, payment status changes, and returns. If the mechanics are two-step — first we credit conditionally, then confirm after payment or shipment, so that bonuses are not issued for unpaid orders.
- Testing on test orders. We run scenarios: a regular purchase, an order with a discount, a partial return, a cancellation after crediting, a purchase under multiple agreements. We verify the customer's balance before and after each operation — a discrepancy in at least one item means an error in the rules.
- Handover and documentation. We provide the rules scheme, handler descriptions, and instructions for managers: how to change the percentage, add categories, and resolve disputed credits. We show where to view the transaction log so that edits do not require calling a developer.
After handover, the mechanics run independently: rules are changed through settings, not through code. If the logic needs to be extended — for example, adding loyalty tiers or a bonus expiration period — the structure is already prepared for it.
What the client receives after implementation
Implementing cashback is not just code, but also a set of artifacts that keep the system running after launch. Below is what remains with the client: accrual rules, an exclusion scheme, a manual adjustment procedure, and documentation.
Each item can be handed over to a new administrator or contractor without retelling it "by word of mouth."
- Accrual rules — a matrix of product categories and catalog sections with percentages, thresholds, and conditions for when accrual starts. It is stored in the module settings, not in the template code, so a marketer can change the percentage without a release.
- Exclusion scheme — a list of products, brands, and promotional items to which cashback does not apply, with rule priority: what wins when a category and a promotion overlap. Exclusions are described declaratively; adding a new item does not break the calculation for the others.
- Two-step accrual — separating "accrued at order time" and "available after payment confirmation or the end of the return period." This removes the risk of payouts on canceled orders and returns.
- Manual adjustment procedure — the administrator's sequence of actions: where to view a customer's balance, how to make an accrual or write-off, which fields are mandatory for the journal, and who confirms the operation. All actions are recorded in the log with the author and reason.
- Documentation — a description of the balance storage structure, integration points with checkout and the customer account, as well as a guide for the support team on typical customer inquiries.
- Operations journal and reporting — export of accruals and write-offs by period, reconciliation with orders, and detection of discrepancies before the customer notices them.
- Procedure for changing rules — how to safely change percentages and categories on a live site: what applies to new orders and what is recalculated for old ones.
Such a package removes dependence on a specific developer: the accrual logic is described, exclusions are formalized, and manual operations are governed by a procedure. Describe your loyalty scheme — we will come back with an estimate and an implementation plan.
Case study: how we eliminated double cashback accruals
The client is a retail chain with a loyalty program on 1C-Bitrix: cashback was accrued in two places — at order placement and by a separate agent upon shipment.
When the connection to the payment gateway dropped or the form was resubmitted, the order was created twice, and bonuses landed on the customer's card as two transactions. The share of erroneous accruals reached 6% of the monthly volume, and sorting out each case fell to support.
What it was before
The problem did not manifest constantly, but in waves — during sales and on days of increased load, when the agent queue fell behind the order flow. Customers saw extra bonuses, spent them, and the reversal already required manual balance adjustment.
Support received dozens of identical requests per week, and accounting received discrepancies between the bonus account and actual shipments.
What we changed
We separated accrual and write-off into different entities and introduced an idempotent operation key: each cashback transaction is now tied to a "order + operation type" pair, and a repeated record with the same key is discarded at the handler level.
The agent was switched to queue mode with locking on a specific order rather than on the entire table — parallel processes stopped overwriting each other's data.
Additionally, we added an operations log with a source attribute: you can see who accrued the bonuses — placement, shipment, or manual operator adjustment.
What it became
The share of erroneous accruals dropped from 6% to 0.2% — these are isolated cases that are caught at the reconciliation stage rather than after a customer complaint.
Support requests on the topic of bonuses decreased by roughly seven times, and manual balance adjustments — almost to zero: the operator intervenes only in genuinely disputed situations.
Reconciliation of the bonus account with shipments now matches automatically, without line-by-line review.
We note separately that the migration was carried out without stopping the loyalty program: old transactions were transferred with assigned keys, and new ones were already written according to the new scheme.
A rollback was provided for — the operations log allows restoring any customer's balance as of an arbitrary date.
How cashback accrual differs in Bitrix and Bitrix24
Cashback accrual in Bitrix and Bitrix24 are two different classes of tasks, even though they share the same core.
In «1C-Bitrix: Управление сайтом», points live in user properties or a separate infoblock structure: you define the storage table yourself, you write the accrual and redemption handlers yourself, and you are responsible for the idempotency of operations yourself.
In Bitrix24, the same mechanism relies on built-in entities — the user's account and internal currency — and accrual goes through the events of the e-commerce module.
The difference is fundamental: in the first case, you build the logic from scratch; in the second, you integrate into a ready-made settlement model.
Point storage determines everything else. When the balance sits in a user property, you get full control over the structure, but you lose ready-made reconciliation and reporting tools — every operation has to be logged manually.
The built-in account in Bitrix24 provides a transaction history, balance locking during checkout, and protection against double redemption under concurrent requests. In practice, this eliminates a whole class of errors that surface in a custom scheme only in production.
Accrual handlers also differ in their connection point. In the «Управление сайтом» editions, accrual is usually hooked to the order placement event or to an agent that recalculates categories on a schedule.
In Bitrix24, it makes more sense to use account events and the rules for working with internal currency — then accrual is synchronous with the movement of money through the order, and no discrepancies arise between the balance and the purchase history.
Edition differences add another layer. The lower «Управление сайтом» editions do not include the e-commerce module in full, so cashback there is built on infoblocks and custom tables.
In the higher editions and in Bitrix24, built-in discount and bonus mechanisms are available, which can be extended with category and exclusion rules.
Before designing, we always verify the edition and the set of connected modules — this determines whether to write the logic from scratch or fine-tune a ready-made one.
The practical takeaway: if you migrate a project from «Управление сайтом» to Bitrix24, do not drag along custom point storage — move it to the built-in account. The reverse migration requires the reverse operation.
We analyze the current storage and handler scheme, show where it will fail under load, and propose a target architecture for your edition.
Let's discuss your cashback task
To come back with an estimate and an implementation plan, we need to understand the current accrual mechanics: where cashback is calculated, which product categories are involved, how exceptions are handled, and how the result reaches the customer.
Describe the task in free form — that is enough for us to determine the scope of work and propose an architecture.
- how cashback is currently accrued: manually, via cart rules, event handlers, or an external service;
- which product categories and catalog sections are involved, and whether there are priorities between them;
- how exceptions are defined: excluded products, brands, promotional items, made-to-order products;
- whether a two-step cashback is needed — preliminary accrual at order placement and final accrual after payment or shipment;
- how cashback is redeemed: partially, fully, with a limit on the share of the order total;
- what the points lifetime is and what happens to them upon a return or order cancellation;
- where the customer sees the balance: personal account, emails, mobile app, external system;
- which integrations are affected: 1С, loyalty program, CRM, warehouse, payment module.
If part of the mechanics is already implemented and works unstably, describe the symptom: points are accrued twice, are not redeemed at checkout, or diverge from 1С after synchronization. Using these details, we will localize the cause faster than from a general description.
Describe the task — we will come back with a timeline estimate, an implementation plan, and the scope of work for each stage.

