It's 6:47 PM on a Friday. A restaurant operator opens their end-of-day report. The POS says they processed $14,832.67 across 187 transactions. Their processor's merchant portal shows $14,619.42 across 184 transactions. Their bank deposit the next morning is $14,301.18.
Three numbers. Three systems. None of them agree.
The operator calls support. The support agent asks the kitchen manager if anyone voided something. Nobody knows. A tip adjustment from a $212 tab might not have settled. A chargeback from Tuesday might have been deducted from today's batch. Or maybe the processor's batch cut happened at 10 PM EST and two late transactions rolled into tomorrow.
This is not an edge case. This is Tuesday. This is every restaurant, every retail store, every merchant running a POS system in production. And the engineers who built the payment integration are usually the last to understand why.
Why engineers underestimate reconciliation
When engineers think about payment systems, they think about the authorization flow. Card in, approval out. There's a clear request, a clear response, and a well-documented API. It's a synchronous operation with a binary outcome — approved or declined. It's satisfying to build and straightforward to test.
Reconciliation is none of those things.
Reconciliation is the process of answering a deceptively simple question: did the money that was supposed to move actually move, in the correct amounts, to the correct accounts, at the correct time? The answer requires comparing data across systems that were never designed to agree with each other — your POS database, the processor's settlement engine, and the merchant's bank.
Most engineers encounter reconciliation late. It's not in the processor's quick-start guide. It's not part of certification test suites. It's the problem that surfaces three months after launch, when a merchant calls to say their deposit is short by $400 and nobody can explain why.
By that point, the architecture isn't built to answer the question.
The fundamental mismatch
Authorization and settlement are two entirely different systems, and they operate on different timelines.
When a customer taps their card, the POS sends an authorization request to the processor. Within seconds, the processor responds — approved, declined, or partially approved. This is a synchronous exchange. The POS knows the result immediately and can act on it.
Settlement is asynchronous. It happens hours later, sometimes the next business day, sometimes two days later depending on the processor, the card network, and the acquiring bank. The processor collects all authorized transactions into a batch, submits that batch for clearing through the card networks, and eventually the funds land in the merchant's account — minus fees, adjustments, and deductions the merchant may not have visibility into.
The problem is that the authorization and settlement don't share a single, stable identifier in many processor implementations. The authorization might use one transaction ID. The settlement report might reference a different internal ID, a batch number, and a truncated card number. Matching them requires building a correlation layer that accounts for every processor's idiosyncratic data format.
Authorization vs. settlement: two timelines, loosely coupled
What actually goes wrong
Reconciliation failures are rarely dramatic. They're death by a thousand small discrepancies, each with a different root cause.
Tip adjustments
In restaurants, a common flow is: authorize the check amount, hand the receipt to the customer, customer writes in a tip, server closes the check with the adjusted total. The authorization was for $48.00. The settlement is for $57.60. This is expected — but only if the tip adjustment is captured and submitted to the processor before the batch closes.
If the batch closes before the adjustment is submitted, the transaction settles at the original authorized amount. The $9.60 tip is lost in the current batch and may or may not appear in the next one, depending on how the processor handles late adjustments. Some processors allow post-batch tip adjustments within a window. Others don't. The POS shows $57.60. The settlement shows $48.00. The merchant is confused. The server wants their tip.
Partial authorizations and split tenders
A customer's card has $30 remaining on a $50 transaction. The processor returns a partial authorization for $30. The POS prompts for a second payment method — cash, another card, a gift card. The original transaction now has two or three funding sources, only one of which flows through card settlement.
If the POS records the full $50 as a card transaction in its local ledger, reconciliation will show a $20 overage against the settlement data. If it correctly records the $30 card portion, it needs to track the remaining $20 in a separate tender bucket. This sounds straightforward, but in practice, the logic for splitting transactions across tender types, handling voids on split tenders, and reconciling each portion against the appropriate settlement stream is a source of persistent bugs.
Voids vs. refunds
A void cancels a transaction before it settles. A refund creates a new credit transaction after settlement. They look the same to the merchant — the customer got their money back — but they behave completely differently in reconciliation.
A voided transaction should disappear from the settlement batch entirely. A refund should appear as a negative entry in a future batch. If a void request times out and the POS doesn't know whether the void was processed, it might submit a refund as a fallback. Now the merchant has both a settled charge and a refund, and the net effect is correct — but the gross numbers are inflated, the transaction count is wrong, and the reports don't reconcile.
Void vs. refund: same merchant outcome, different settlement behavior
Chargebacks
A chargeback is initiated by the cardholder's bank, not by the merchant or the POS. It can arrive days, weeks, or months after the original transaction. When a chargeback is processed, the disputed amount is deducted from the merchant's settlement — often from a completely unrelated batch.
From the POS's perspective, a chargeback is invisible. The POS has no record of it unless the processor provides chargeback notifications through a webhook or a reporting API. Many processors provide this data, but the format, timing, and completeness vary. Some processors deduct chargeback amounts silently from the next deposit. The merchant sees a smaller deposit than expected and has no way to trace the deduction back to a specific transaction without logging into the processor's portal and cross-referencing manually.
Batch timing
Processors don't all close batches at the same time. Some auto-close at a fixed time — say, 10 PM Eastern. Others allow the merchant to trigger manual batch close from the terminal. Some close based on the processor's internal schedule, which may not align with the merchant's business day at all.
A restaurant that stays open until midnight in Pacific time might have its batch auto-close at 7 PM local time. Transactions after 7 PM roll into the next day's batch. The POS end-of-day report covers the full business day. The settlement covers a partial day. The two will never agree unless the POS is aware of the batch cut time and adjusts its reporting window accordingly — something few POS systems do.
The processor inconsistency problem
If reconciliation were difficult with a single processor, it might still be manageable. But POS platforms that serve multiple merchant verticals or geographies almost always need to support multiple processors. And each processor's settlement data is structured differently.
Processor A might provide a daily CSV with one row per transaction, using their internal reference ID, the authorization code, the last four digits of the card, and the settlement amount. Processor B might provide a PDF report grouped by batch, with subtotals but no per-transaction detail. Processor C might expose a reporting API that returns JSON, but only retains data for 30 days. Processor D might send a daily email with an Excel attachment.
The identifiers don't match. The amount formats differ — some include fees, some don't. Some report in the merchant's local currency, others in the settlement currency. Some include chargebacks in the settlement report, others report them separately. Some provide real-time settlement data, others are delayed by 24 to 48 hours.
Building a reconciliation engine that normalizes all of this into a single coherent view is a significant engineering effort. It requires processor-specific adapters, robust data ingestion pipelines, and a matching algorithm flexible enough to handle approximate matches when identifiers don't align perfectly.
Multi-processor settlement data: no two formats alike
Payments people vs. systems people
There is a cultural gap that makes reconciliation harder than it needs to be, and it sits between the people who understand payments and the people who build the systems.
Payments people — operations managers, merchant services reps, finance teams — think in terms of money movement. They care about when funds land, which fees were deducted, and whether the deposit matches the batch total. They live in settlement time. Their mental model is accounting: debits, credits, adjustments, net amounts. When something is wrong, they look at the money and work backward to the transaction.
Systems engineers think in terms of requests and responses. They care about API contracts, idempotency, error codes, and state machines. They live in authorization time. Their mental model is distributed systems: a request was sent, a response was received, the state was updated. When something is wrong, they look at the logs and work forward from the event.
Reconciliation sits exactly at the seam between these two worldviews, and neither side fully owns it. The finance team knows what the numbers should be but can't debug why they aren't. The engineering team can trace every API call but doesn't know what the settlement file means or why a transaction that returned 200 OK three days ago is now missing from the deposit.
The best reconciliation systems are built by teams that have internalized both perspectives — teams where an engineer can read a settlement file and a finance analyst can describe what a batch close does. In practice, this rarely happens. The two groups operate on different timelines, use different vocabulary, and report to different parts of the org. Reconciliation falls into the gap between them.
The state problem
Reconciliation requires the POS to maintain a richer transaction state model than authorization alone demands.
During authorization, a transaction has a simple lifecycle: pending, approved, declined. That's sufficient for the point of interaction. But for reconciliation, the POS needs to track a much longer tail of states: authorized, adjusted, voided, settled, partially settled, charged back, refunded, disputed, and failed to settle. Each state transition might originate from a different system — the POS itself, the processor's batch engine, the card network, or the cardholder's bank — and might arrive hours or days after the original transaction.
Most POS systems are not designed with this extended state model in mind. The transaction table has an amount and a status column. Maybe an is_voided boolean. There is no settlement_amount, no settlement_date, no chargeback_amount, no adjustment_history. When reconciliation discrepancies surface, there's nowhere to store the explanation.
I call this settlement amnesia — the system faithfully records the moment of sale but forgets the transaction immediately after. It has no memory of what happened during clearing, no awareness of batch outcomes, no capacity to absorb the corrections and reversals that follow. The transaction is born, approved, and then abandoned by the data model. Everything that happens to it after the receipt prints — which is where all the money questions live — happens in a void.
Settlement amnesia is not a bug. It's the natural consequence of building a transaction model for authorization and assuming settlement would just work itself out. It always does, until it doesn't.
Retrofitting this state model onto an existing system is painful. It touches the core data model, the API contracts, the reporting logic, and the UI. It's the kind of change that should have been designed in from the beginning — and almost never is.
Transaction state: what authorization sees vs. what reconciliation needs
Why you can't bolt it on later
The instinct in most POS engineering teams is to treat reconciliation as a reporting problem. Build the payment integration first. Get transactions flowing. Then add a reconciliation report that compares POS data against processor settlement files.
This approach fails because reconciliation isn't a read-only operation on existing data. It requires data that was never captured.
If the POS didn't store the processor's batch ID at authorization time, there's no way to correlate the transaction with the batch it settled in. If the POS didn't record the exact timestamp the processor returned — not the POS's local clock, but the processor's timestamp — batch boundary calculations will be wrong. If the POS didn't persist the original authorized amount separately from the final settled amount, tip adjustments and partial authorizations can't be tracked.
These are not reporting gaps. They are data model gaps. And they can't be filled retroactively for transactions that have already been processed.
The teams that get reconciliation right are the ones that design for it before writing the first authorization request. They build the transaction state model with settlement in mind. They capture every identifier the processor returns, even the ones that seem redundant during authorization. They design the batch management layer to be processor-aware, not processor-agnostic.
This is unintuitive. Engineers want to abstract away processor differences — build a clean interface that treats all processors the same. But reconciliation punishes abstraction. The details that differ between processors — batch timing, identifier formats, adjustment windows, fee structures — are exactly the details that reconciliation depends on. A clean abstraction that hides them is an abstraction that makes reconciliation impossible.
The architectural implication
Reconciliation is not a feature. It's an architectural property. Either the system was designed to support it, or it wasn't. There is no middle ground, and there is no shortcut.
The systems that handle reconciliation well share a common trait: they treat the transaction as a long-lived entity with a lifecycle that extends far beyond the point of sale. The authorization is the beginning of the transaction's life, not the end. Settlement, adjustment, chargeback, and dispute resolution are all subsequent chapters, and the system needs to be ready to record each one.
This means reconciliation isn't something you add to a payment system. It's something you either build the payment system around, or you spend years patching. Most teams learn this the hard way — usually around the time a merchant calls to ask why their deposit is short and nobody in engineering can answer the question.
The deposit will always be short eventually. The only question is whether your system can explain why.
Here's the thing nobody tells you when you start building payment integrations: the authorization is the easiest financial event your system will ever handle. Everything after it — settlement, adjustment, dispute, reversal — is harder, slower, less documented, and more consequential. And yet we design our systems as if the authorization is the main event and everything else is cleanup. That inversion — building the system around the simplest moment and neglecting the hardest ones — is why reconciliation breaks. It's not a technical failure. It's a failure of imagination about what a payment actually is. A payment isn't a request and a response. It's a weeks-long, multi-party process that your system either participates in or gets surprised by.
This is part of an ongoing series on payment infrastructure and POS system design. Previous articles in this series cover processor fragmentation and offline payment handling.