A junior engineer finds a bug in the contribution allocation logic. The fix is three lines. The affected batch covers 47,000 participants across eleven days. The instinct — reasonable in almost any other domain — is to fix the code, replay the batch, and move on.
In BES, that instinct is what turns a contained defect into a multi-quarter reconciliation project.
Why Replay Is Not Correction
In most data pipelines, a replay is idempotent by design. You reprocess the input, overwrite the output, and downstream consumers get the corrected view. The mental model is: the pipeline is a function, and we're just re-evaluating it with the fixed version.
BES pipelines are not functions. They are event emitters into a legally binding chain.
When the original batch ran, it did not just produce a number. It produced:
- A state contribution claim submitted to the Treasury (devlet katkısı talebi)
- An EGM submission recording the participant's fund allocation on that valuation date
- A NAV that priced the fund for every other participant that day
- Unit counts credited to accounts, which were then used as the basis for subsequent days' calculations
- Tax withholding events on any exits that occurred against those unit counts
Each of those is a separate legal artifact with its own custodian, its own audit trail, and its own party who has already acted on it. Replaying the batch does not correct those artifacts. It creates a second, conflicting version of them.
A Concrete Example
Assume the bug caused the employer contribution matching component to be under-allocated by 0.4% for eleven days. The fix is correct. The replay is straightforward. The output now shows the right unit counts.
Here is what the replay just did:
-
State contribution mismatch. The 25% state contribution was already calculated and requested against the original (lower) contribution amount. Treasury has either paid it or scheduled it. The replayed figure implies a different state contribution — but you cannot retroactively increase a state contribution claim for a closed period without going through a formal correction submission, and EGM will reject the file if the participant-level totals don't tie to what they already have on record.
-
NAV contamination. The fund NAV on each of those eleven days was computed using the total units outstanding, which included the buggy allocations. Every other participant in that fund was priced against that NAV. If you now change the unit counts retroactively, the historical NAVs become inconsistent with the unit register. You have two choices, both bad: leave the NAVs alone and accept that unit × NAV no longer reconciles to fund AUM, or restate the NAVs and trigger a cascade of corrections for every participant who transacted during those eleven days.
-
Exit events already priced. Any participant who exited, switched funds, or took a partial withdrawal during or after the affected window transacted against the original unit counts at the original NAVs. Those events settled. Tax was withheld and remitted. Restating the underlying units means those exits were technically executed at the wrong price, which is not a bug fix — it is a reversal of settled financial transactions.
-
Downstream day dependencies. Day 12's calculation used Day 11's closing units as input. Day 13 used Day 12. If you replay days 1–11 with corrected logic, you have not fixed anything unless you also replay days 12 through today, which means every day since has to be recomputed and every downstream artifact from every one of those days has to be reconciled.
The original bug affected 47,000 participants by 0.4% for eleven days. The replay affects every participant in every affected fund for every day since, plus every counterparty who received a submission based on the original numbers.
The Pattern I Keep Seeing
Teams under-estimate this because their test environment does not have the legal downstream. In test, replay works. In test, the corrected output is the corrected output. There is no Treasury, no EGM, no custodian, no tax authority holding a copy of the original.
Production is different not because the code behaves differently, but because production has memory held by parties you do not control. Once a state contribution request has been submitted, once a NAV has been published, once units have been credited and transacted against — those events exist outside your pipeline and cannot be replayed.
What Actually Works
The correction pattern that survives audit is not replay. It is forward correction with explicit adjustment events:
- Leave the historical outputs untouched. They are the record of what happened, correct or not.
- Compute the delta between the buggy output and the correct output at the participant level.
- Book the delta as a dated adjustment event, with its own transaction type, its own audit reference, and its own submission to EGM as a correction rather than an overwrite.
- Handle the state contribution delta through the formal correction channel, not by resubmitting the original period.
- Do not touch historical NAVs. The adjustment flows through as a new unit credit at today's NAV, with a documented reason code tying it back to the original defect.
This is uglier. It leaves a visible scar in the participant's account history. It requires operational sign-off and often a communication to the participant. It is slower than a replay by a factor of ten.
It is also the only approach that does not create a second problem larger than the first.
The Rule
In systems where your output is somebody else's input of record, replay is not a technical operation. It is a legal claim that the past did not happen the way the past says it happened.
Fix forward. Adjust explicitly. Leave the history alone — even when the history is wrong.