Handle exchange API order event ordering by merging observations under the venue's documented rules, preserving confirmed cumulative fills and counting each execution once. A later-arriving status message is not necessarily a newer order state, and repeated Filled messages are not additional trades. Keep status, cumulative quantity and individual executions separate; investigate conflicts before allowing another action that depends on the disputed state.
A filled order can appear to become partially filled again when an older query result finishes processing. The exchange does not need to reverse the trade for a local application to display that mistake. This guide examines the merge decision after observations reach the application. The separate WebSocket recovery guide covers missing sessions and continuity gaps.
The worksheet below uses fictional quantities and processing delays. It is an educational design review, prepared with AI assistance, rather than a report of a customer incident or a claim that KLINEO implements the proposed event consumer.
Define which order can change
Before comparing timestamps, establish identity: exchange, environment, account or subaccount, product category, instrument and exchange order ID. Keep a client order identifier as a mapping where available. An observation for another account cannot update this order merely because a numeric ID matches.
Then separate three records:
- The order projection: latest justified status, accepted quantity revision, cumulative executed quantity and working remainder.
- The execution ledger: distinct trade executions, including quantity, price and fee information. Only records representing trades contribute to filled quantity.
- The observation log: what arrived, its source and documented event or update time, and the local receipt time.
The trade IDs versus order IDs guide explains the one-order-to-many-executions relationship. A message envelope is another identity again: one envelope can contain several execution records. Treating the envelope as the trade loses that distinction.
Bybit's V5 execution stream documentation explicitly permits multiple executions for one order in one message and provides separate execution IDs and quantities. It also notes that simultaneous transactions can share a sequence and different symbols can share it. A sequence alone is therefore unsuitable as an individual fill key.
Respect a guarantee's exact boundary
Do not start with the blanket assumption that exchange WebSocket events always arrive out of order. Binance's current COIN-M user data stream contract specifies ordering by transaction time and event time for the same user, same event type and single connection. It also warns that REST queries can lag during volatile conditions.
That scoped guarantee does not order an application's separate database workers, an earlier REST query and a later stream update into one universal timeline. An ordered stream can still be processed incorrectly if slow work commits after fast work. Preserve the provider's sequence through the processing path where its contract requires it.
Record receipt time for latency diagnosis. Use documented exchange update times or sequence semantics for state comparisons. A local arrival timestamp says when this consumer saw an observation; it does not establish when the order changed.
Equal timestamps need an explicit policy. Millisecond time is not a universal event identity. Two observations at the same time might contain different executions or different fields. Keep their evidence and resolve them using the documented protocol rather than discarding one arbitrarily.
A five-observation merge worksheet
Consider a hypothetical buy order for 10 ABC. Assume one unchanged order identity and accepted quantity, no corrections, and two actual trades: execution F1 buys four units and F2 buys six. Prices and fees are omitted because the exercise tests gross quantity recognition.
The time labels below describe fictional exchange updates. This is application processing order, including a delayed query result, rather than a claimed venue delivery sequence. The initial execution ledger is empty.
| Processing step | Observation | Preserved cumulative gross fill | Distinct execution ledger total | Additional quantity recognized in order projection |
|---|---|---|---|---|
| 1 | Update at t20: partially filled, cumulative 4; F1 detail also available | 4 ABC | 4 ABC | 4 ABC |
| 2 | Update at t30: filled, cumulative 10; F2 detail not yet processed | 10 ABC | 4 ABC | 6 ABC |
| 3 | Earlier query finishes: partially filled, cumulative 4, update t20 | 10 ABC | 4 ABC | 0 ABC |
| 4 | Same filled observation is processed again | 10 ABC | 4 ABC | 0 ABC |
| 5 | Delayed execution F2 detail: quantity 6 | 10 ABC | 10 ABC | 0 ABC |
After step 2, the aggregate supports 10 filled units while the detailed ledger explains only four. The six-unit difference is an execution-detail gap to reconcile. It does not justify inventing F2's price or fee.
After step 3, replacing the projection with the last processed row would erase six confirmed units and reopen a filled order. Preserve the older observation for diagnosis without accepting that regression. Step 4 adds no quantity. Step 5 explains the missing six units without acquiring six more.
The final gross total is 4 + 6 = 10 ABC. Adding both the cumulative total and execution ledger would produce 20 fictional units. Choose one defined accounting authority and use the other view as a reconciliation check. The partial-fill management guide extends the accounting to fees, net inventory and working remainders.
Merge evidence, not a ranked list of status words
A simple status ranking cannot encode every venue lifecycle. Triggered orders, amendments, expirations and cancellation outcomes need product-specific interpretation. Nor should two terminal statuses be resolved by whichever string sorts higher.
For an ordinary unchanged order without documented corrections, a smaller cumulative quantity in an older observation should not reduce confirmed fills. Use the following review rules:
| Incoming evidence | Merge decision to verify |
|---|---|
| Older status and smaller cumulative total | Retain evidence; preserve the newer justified projection |
| Repeated terminal observation with unchanged quantity | Record or deduplicate it; produce no second fill effect |
| Previously unseen execution detail | Insert once under the proper scoped identity; reconcile against the aggregate |
| Newer status but lower cumulative total | Flag a conflict; check identity, units, quantity revisions and documented adjustment rules |
| Conflicting terminal outcomes without a usable ordering rule | Keep the order unresolved pending authoritative reconciliation |
A cumulative high-water mark is a defensive check for this ordinary case, not a universal settlement rule. If the venue documents execution corrections or reversals, those require an explicit adjustment path. Taking the largest number forever would hide a legitimate correction. An accepted quantity amendment also changes the bounds being checked.
Bybit documents a specific race that can emit two Filled order notifications: an execution completes while cancellation is being processed, followed by a cancellation rejection. Those messages describe one completed order and the cancellation outcome. They do not establish two full executions. See the Bybit private-order duplicate Filled warning.
Keep follow-up effects consistent through retries
Correct display state is insufficient if duplicate processing also sends another exit, alert or downstream instruction. Commit the deduplication decision and any resulting effect record together durably so a restart does not forget that work already happened. For an external action, retain a stable effect identity through delivery retries; a database commit alone does not guarantee the recipient applied it once. The trading idempotency guide covers the separate problem of preserving order intent through retries.
Test the merge policy with the worksheet's five steps, then repeat step 4 after restarting the consumer. The resulting gross quantity should remain 10 and previously completed effects should remain single. Also test two distinct executions with the same timestamp, a wrong-account observation, and a newer contradictory cumulative total. The last case should expose uncertainty rather than silently choose a convenient number.
Authentication and event interpretation need separate checks. Correctly signing a request proves neither that an old response is current nor that an order observation was merged correctly. The API passphrase versus secret guide explains those credential roles; keep secrets and signed headers out of observation logs.
A useful final order record states its justified cumulative fill, whether execution details reconcile, its current lifecycle evidence and any unresolved conflict. If a later trading decision depends on a disputed value, keep that decision pending under the operating policy. An attractive current status label cannot substitute for an explained quantity.
