Case Study — Data Integrity Engineering

The Numbers Were Wrong: Rescuing an AP Platform from Its Own Sync

A mid-market distributor's accounts-payable dashboard was overstating the amount due by an eight-figure sum — and the sync feeding it reported green on every run. One overnight full-system review found the mechanism, purged the corruption with a self-healing upsert, and made the entire failure class impossible to repeat silently.

67%
Duplicate rows eliminated
2.5 → 9
Data-accuracy score (/10)
0
Errors in self-healing purge
17
Workflows re-pointed to live alerting
Role Lead Engineer
Stack React / Keycloak / NocoDB / n8n / Xero API
Timeline One overnight review + same-night fix
01 — The Problem

A Dashboard Nobody Trusts Is Worse Than No Dashboard

A mid-market distributor ran its supplier payments through a Keycloak-authenticated React SPA sitting over a no-code data layer, kept in sync with the company's cloud accounting system by an automation workflow. The platform looked finished. The numbers on it did not add up — panel totals disagreed with each other, disagreed with the accounting system, and the headline amount due was overstated by an eight-figure sum. Finance staff had quietly stopped believing the screen and gone back to cross-checking spreadsheets, which meant the platform was now generating work instead of removing it.

The dangerous part was the shape of the failure. Nothing was down. No error had ever fired. The sync workflow showed a perfect record of green runs while it corrupted the invoice table on every single cycle. Each sync requested page one of the accounting API with a duplicated pagination parameter — the workflow appended its own page counter alongside a static page=1, the API honored the first one, and the same page of invoices came back up to eight times per run. The upsert step then bulk-inserted every copy with no within-run deduplication.

The result compounded silently for months: the invoice table grew to 4,063 rows of which only 1,338 were real invoices — 67% of the table was duplicates — and every duplicate row inflated the amount-due totals a little further. A monitoring stack that only watches whether jobs succeed can never catch this class of failure. The job was succeeding. It was the data that was failing.

02 — The Diagnosis

Reconcile Every Displayed Number Back to the Source of Truth

The review method was deliberate: in a single overnight full-system pass, Del Rey traced every number the dashboard displayed back through the data layer to the accounting system — treating the accounting API as the read-only source of truth and refusing to accept any figure that could not be reproduced from it.

Cloud Accounting API source of truth read-only — always page 1 ×8 SYNC WORKFLOW status: green, every run static page=1 param + duplicated page param API honors the first one bulk-insert every copy no within-run dedup ×N copies Invoice Table 4,063 rows 1,338 real invoices 67% duplicates AP Dashboard React SPA 8-figure overstatement every cycle repeats the insert — corruption compounds while monitoring stays green

The reconciliation surfaced the whole chain in one night. The invoice table held 4,063 rows against 1,338 real invoices in the accounting system. Grouping by invoice identifier showed the duplicates were exact copies stamped by successive sync runs — which pointed straight at the fetch step, not at user behavior or the accounting data itself. Reading the workflow's HTTP nodes exposed the smoking gun: a static page=1 query parameter sitting alongside the paginator's own same-name parameter. The API honored the first, so "fetch all pages" degenerated into "fetch page one, up to eight times."

The same pass caught what a narrower bug hunt would have missed. A display-priority rule on payment folios was inverted — a short internal folio was outranking the full invoice reference everywhere it appeared, so staff saw truncated identifiers on documents that demanded exact ones. Role checks that looked enforced in the UI were not enforced behind it. And buried in the workflow history was a previous incident: a stale credential had silently stopped payment notifications for roughly 21 hours, and nothing had alerted anyone — the same monitoring blind spot as the sync, wearing a different disguise.

One review, one method — trust nothing the screen says until the source of truth reproduces it — and the platform's three separate problems turned out to be one problem: failures that don't announce themselves.

03 — The Fix

Dry-Run, Verify, Delete, Converge to Zero

Deleting 2,725 rows from a production financial table is not a script you run and hope. The fix was engineered as an idempotent, self-healing upsert with a hard discipline around every mutation — prove the plan before executing it, and prove convergence after.

01
Protect
Full Backup
exported before any mutation
02
Simulate
Dry Run
reports what WOULD be deleted
03
Reconcile
Verify Surplus
2,725 — exact vs source
04
Execute
Live Delete
2,725 removed, 0 errors
05
Prove
Converge
next cycle: surplus 0
1

Read-Only Posture Against the Accounting System

The cloud accounting system was treated as an untouchable source of truth for the entire operation. Every call against it was a GET; every mutation happened only in the platform's own data layer. Whatever went wrong downstream, the client's books could not be damaged by the repair — a constraint set before the first command ran, not negotiated afterward.

2

Full Backup Before Any Mutation

The complete invoice table — all 4,063 rows, duplicates included — was exported before a single row was touched. If the dedup logic had a flaw, the rollback was one restore away. Backups of prior state preceded every destructive step in the engagement, not just the headline purge.

3

Dry-Run First — Report, Don't Act

The rebuilt sync runs its full dedup pass in a reporting mode before it is allowed to delete: group rows by invoice identifier, keep the newest row per invoice (the one matching current accounting-system state), and emit the surplus it would remove. The dry run reported a surplus of exactly 2,725 rows — no deletion yet, just an auditable plan.

4

Verify the Plan Against the Source of Truth

Before going live, the arithmetic had to close: 4,063 rows in the table, 1,338 real invoices in the accounting system, surplus 2,725 — an exact match, to the row. Per-entity totals were reconciled against the deduped baseline to the cent, both before and after. A dry run that had reported any other number would have stopped the operation cold.

5

Live Delete — 2,725 Rows, Zero Errors

Only after the dry run matched the source of truth did the purge run live: 2,725 surplus rows removed with zero errors, leaving 1,338 rows and zero duplicate groups. The root cause was fixed in the same release — the duplicated pagination parameter eliminated, real pagination-to-the-end wired in, and within-run deduplication added so the upsert is idempotent by construction.

6

Converge to Zero — and Keep Converging

The proof of an idempotent, self-healing sync is its next cycle. It ran on schedule against the cleaned table and reported: surplus 0, deleted 0, 0 errors. And because the dedup pass now runs inside every sync, the pipeline doesn't just avoid re-corrupting the table — if duplicates ever appear again by any path, the next cycle detects and heals them, and surfaces the anomaly instead of swallowing it.

"A sync that reports green while corrupting the table on every cycle is the most dangerous failure in production — because no one is looking for it."
React 18 + Vite Keycloak OIDC Node + Express NocoDB n8n Xero API Postmark Docker / Coolify
04 — Prevention & Results

Making the Silent-Failure Class Impossible to Repeat

Cleaning the data was half the job. The other half was making sure the platform can never again fail quietly — no workflow without a live error handler, no day without a health signal, no number on screen that the source of truth can't reproduce.

2,725
Surplus rows purged
0
Surplus on next sync cycle
17
Workflows on live alerting
2.5→9
Data-accuracy score (/10)

17 Workflows Re-Pointed to a Live Error Handler

The review uncovered an earlier stale-token outage that had silently stopped payment notifications for roughly 21 hours — nothing alerted, because the workflows' error paths pointed nowhere useful. All 17 automation workflows were re-pointed onto a live error handler, so a failed run now produces an immediate, human-visible alert instead of a quiet gap.

A Proactive Daily Health Digest

Error handlers catch loud failures; the digest catches quiet ones. A daily health report now summarizes sync outcomes, row counts, and anomaly signals — so a failure mode that produces no error but wrong data, the exact class that caused this incident, surfaces within a day instead of compounding for months.

Display Priority Corrected on Payment Folios

An inverted priority rule had the short internal folio outranking the full invoice reference across the platform. The precedence was flipped everywhere it appears, so finance staff see the complete, unambiguous document reference — recorded as a client-approved decision, not a silent change.

RBAC Enforced Behind the UI, Not Just in It

Role checks that existed only in the interface were hardened into server-side enforcement: writes to the data layer now require an elevated role on a verified token, fail-closed, with a proper read-only tier for operational staff. Authorization the UI merely implied is now something the backend guarantees.

Have Numbers Nobody Trusts?

I rescue production data systems — tracing every displayed figure back to its source of truth, fixing the mechanism instead of the symptom, and proving convergence before I call it done.

Let's Work Together
VERIFIED DELIVERY RECORD →