Intercompany reconciliation clears the balances two entities book against each other before those balances roll into a consolidated close. Breaks appear because the two ledgers rarely agree on reference, currency, or posting date. The fix is entity resolution across both ledgers plus a matcher that tolerates the legitimate differences and isolates the genuine one-sided entries underneath.
Take a common case. Entity A books a charge on trade date in EUR; Entity B books the same charge on settlement date in USD, under a different narrative and a different invoice number. An exact match fails, and a break appears that is really one transaction seen twice. The naive fix is a spreadsheet with a SUMIF that assumes both sides used the same reference and the same currency on the same day. They did not. Real reconciliation is entity resolution across two ledgers configured by different teams, in different systems, under different local GAAP conventions, followed by a matching step that tolerates the differences that are legitimate while flagging the ones that are not.
Where the breaks actually come from
Before any model, name the categories, because they need different treatment and a single “match rate” number hides all of them.
- Timing differences. One entity posts on trade date, the counterparty on settlement or on receipt of an invoice. The amounts agree; the periods do not. At quarter-end these dominate and most of them self-clear in the next period.
- FX differences. Each side books in its functional currency. A GBP receivable against a USD payable will never tie to the cent unless you fix a rate and a point in time for the comparison.
- Reference mismatch. Purchase order on one side, internal cost-allocation code on the other, a free-text memo on a third. There is no shared key, so matching has to lean on amount, date proximity, entity pair, and text similarity together.
- Genuine one-sided entries. A charge one entity booked and the other has not accrued at all. These are the breaks that matter, and the whole point of the pipeline is to stop the first three from burying them.
If you cannot bucket a break into one of these, you cannot decide who acts on it. So the classifier that assigns the category is as important as the matcher that pairs the records.
The matching pipeline
We treat this as blocking, then scoring, then resolution.
Blocking cuts the candidate space. You do not compare every posting in Entity A against every posting in Entity B; you group by entity pair and a date window wide enough to absorb the largest legitimate timing gap you have measured, usually a few business days around period boundaries. This keeps the scoring step tractable and, more importantly, keeps false positives down because you are never scoring pairs that could not plausibly be related.
Scoring compares candidates on several signals at once: amount agreement after FX translation to a common currency at a single point-in-time rate, date proximity, entity-pair validity, and reference or narrative similarity. The FX step has to be point-in-time correct. Translate each side at the rate that applied on its own posting date to a common reporting currency, then compare; do not compare a stale reporting-currency balance against a freshly revalued one, or you invent a break that is entirely an artefact of when the two snapshots were taken.
Resolution decides. A high combined score with a small, explainable residual inside your value band clears as a timing or FX difference and the pipeline proposes the eliminating journal. Everything else is a candidate break with its evidence attached: the two postings, the signals that did and did not agree, and the rate used. A reviewer is looking at a case, not a raw ledger dump.
The false-positive budget is the design constraint people skip. A matcher tuned to pair aggressively will clear real one-sided entries by accident, which is the one error you cannot afford at close because it removes a genuine break from view. We tune toward recall on the break side: when in doubt, surface it. That means a higher manual queue, and it means the manual queue has to be fast to work, which is why the evidence bundle matters more than the raw match percentage.
Making it hold up at close
A number in an elimination journal has to be defensible weeks later when an auditor asks how these two postings became one. That is an audit-trail and lineage problem, and it is where most quick automations fall over.
- Lineage on every clear. Each auto-cleared pair records the source rows, the rate and its source, the rule or model version that matched them, and the score. Reproducing the decision cannot depend on re-running a model that has since drifted.
- A frozen eval set of known breaks. Take a period you have fully reconciled by hand and hold it back. Every change to blocking windows, scoring weights, or thresholds runs against it before it touches live close data. Without this you are tuning on vibes and discovering regressions during quarter-end.
- Rate governance. Decide once which rate source and which time convention you use for the point-in-time translation, and store it with the match. When two people disagree about a residual, it is almost always because they translated at different rates.
- Drift watch on the mix. Track the category split over time. A sudden rise in reference-mismatch breaks usually means an upstream system changed how it stamps references, not that reconciliation got worse. The pipeline should tell you which.
Chasing a model that clears everything is the wrong target. A good pipeline pushes the timing and FX noise through automatically, hands a reviewer a short queue of real breaks with the evidence already assembled, and leaves a record that survives the audit. Get the entity resolution and the point-in-time FX right and the matching stops being the hard part. The hard part becomes the two upstream ledgers that were never designed to agree, which is exactly where the work should go.
FAQ
Why do intercompany accounts break even when both sides post the same trade?
The two ledgers rarely share a reference, a currency, or a posting date. One side books in EUR on trade date, the other in USD on settlement date with a different narrative, so an exact match fails and a break appears that is really the same transaction seen twice.
Should we net intercompany balances before or after FX translation?
Match in transaction currency first, then translate the matched pair using a single agreed rate. Netting after each side has been translated independently bakes two different FX rates into one relationship and produces a residual that looks like a real break.
Can a model post the correcting journal on its own?
It should propose the journal and route it. Below a confidence threshold and inside a defined value band it can auto-clear timing differences; anything touching FX revaluation or a manual reference override goes to a human, with the evidence attached.