Skip to content
Centriu
Centriu Loop

Balance Update Atomicity Automation: Spending Every Last Cent Was the One Case That Broke

Centriu Loop's own balance-update mechanism previously applied every ledger movement to a customer's running balance using a single "insert a new balance row, or update the existing one on conflict" database statement — a genuinely correct, standard pattern for keeping a per-customer summary row in sync with an underlying transaction log. Alongside a fix adding a database-level guarantee that a balance can never go negative, this exact pattern broke on one specific, entirely ordinary transaction: a customer redeeming their ENTIRE remaining balance, bringing it to precisely zero. PostgreSQL's own execution order is the reason: it validates a table's CHECK constraints against the row a statement is PROPOSING to insert BEFORE it ever determines whether an existing row will cause that statement to resolve as an update instead. The statement in question always proposed an insert row carrying the raw, standalone value of the CURRENT movement alone — for a debit, a negative number — which the new non-negative-balance CHECK correctly rejected as invalid, even though the transaction that would ACTUALLY run, once the conflict was resolved, was an update adding that same negative delta to an existing positive balance, arriving at exactly zero — a value the CHECK would have accepted without issue. A completely legitimate, common transaction — spending a balance down to nothing — was refused with a database constraint error, specifically because of how PostgreSQL orders its own validation relative to conflict resolution, not because of any actual mistake in the amount being redeemed. The fix replaces the single conflict-resolving statement with an explicit two-step sequence: attempt an update first, and only fall back to an insert if no existing row was found to update — closing the gap because an update's own CHECK validation is always performed against the row's actual, final resulting values, never against a hypothetical proposed insert that will never actually happen.
Exact-balance redemption failed
Now update-first, always correct
Wallet balance and redemption screen
Spending every last cent was the one case that broke.

A database checks the row you propose, not the row that will actually exist

A single database statement designed to either insert a new row or update an existing one on conflict is a genuinely elegant, efficient way to express "make sure this record reflects the latest value," and it is entirely correct for the overwhelming majority of writes that use it. Its specific, narrow blind spot is a matter of validation ORDER, not logic: the database has to decide what row it is proposing to write before it can know whether that proposal will collide with something already there and get redirected into an update instead — and any constraint checked at that proposal stage is checked against a row that, in the conflict case, will never actually be the row that ends up stored.

How the underlying problem shows up before you fix it

A single combined "insert, or update on conflict" statement is used to apply an incremental change (a delta) to a running total stored on an existing row.

A newly-added CHECK constraint on the target column (here, a non-negative balance requirement) is validated against the statement's own PROPOSED insert row — which, for an existing record, carries only the raw incoming delta, not the delta combined with whatever value is already stored.

A transaction that is completely legitimate in its ACTUAL, final effect (a debit that reduces an existing positive balance to exactly zero) is rejected, because the value that would exist in isolation — the delta alone, without the pre-existing balance added to it — fails the same check the correctly-combined final value would have passed.

This class of defect specifically targets the EDGE of a valid range — here, spending a balance down to precisely zero, rather than leaving any amount unspent — meaning ordinary testing that redeems only a PARTIAL balance can pass repeatedly while the one boundary case that matters most (using every last unit available) fails every time.

The failure surfaces as a database-level constraint violation with a specific, identifiable error code, rather than a vague or generic failure — but the code alone does not explain WHY a transaction that looks correct on paper is being rejected, unless the statement's own two-phase resolution order is already understood.

Why a combined insert-or-update statement feels safe until a constraint checks the wrong candidate

A single "insert, or update on conflict" statement is specifically designed to be safe against a RACE — two callers attempting to create or update the identical row at nearly the same instant — which makes it an attractive, natural choice for exactly the kind of running-balance update a ledger needs. What that pattern does not automatically guarantee is that every constraint on the target table is validated against the value that will actually END UP stored; a constraint checked at the PROPOSAL stage, before the database has resolved whether an insert or an update will actually happen, is validated against a candidate row that may bear little resemblance to the row that is about to be written for real. The gap is invisible for as long as the delta alone happens to satisfy the same constraint the final, combined value would — and becomes visible specifically at the boundary where a raw delta and its correctly-combined final result diverge, such as any debit whose SIZE happens to exactly match the balance it is being applied against.

How Centriu Loop fixed the one debit that would always fail

Centriu Loop's own balance-update mechanism applies every ledger movement — a credit, a debit, an adjustment, an expiration, a chargeback — to a customer's single running-balance row using a database trigger. Before this fix, that trigger issued one combined "insert a new balance row, or update the existing one on conflict" statement per movement, proposing an insert row that carried only the incoming movement's own raw value.

Alongside this same fix, a new database-level constraint was added requiring a customer's available balance to never go negative — closing a separate, real gap where the balance had previously carried no such guarantee at all. The two changes interacted in one specific, previously-untested way: a legitimate debit that would reduce an EXISTING positive balance down to precisely zero proposed an insert row carrying the raw, negative delta on its own — a value the new non-negative-balance constraint correctly rejects in isolation, even though the transaction that would actually execute, once the database resolved the conflict against the existing row, was an UPDATE adding that same negative delta to the existing positive balance and landing at exactly zero, a value the same constraint fully permits. Because PostgreSQL validates a statement's CHECK constraints against the row it is proposing to insert BEFORE resolving whether that proposal will instead become an update, the constraint saw only the doomed, isolated proposal — never the correct, combined value that would genuinely result.

The fix replaces the single combined statement with an explicit two-step sequence: attempt an UPDATE against the existing row first, applying the movement's delta directly to whatever value is already stored; only if no existing row is found for that customer does the logic fall back to an INSERT, seeded with the movement's own values as the customer's very first record. An UPDATE's own CHECK validation is always performed against the row's actual, final resulting values — never against a hypothetical proposed insert that, for an existing customer, will never actually be the row that gets written — which eliminates the specific gap entirely rather than working around it for this one balance's specific shape of transaction. A remaining, narrow race between two truly simultaneous FIRST-EVER movements for the same brand-new customer (where neither has yet created the row for the other to update against) is handled by retrying the loop once the concurrent insert is detected, rather than by reverting to the original combined statement.

The fix was caught, not guessed at: a real PostgreSQL test battery exercising every legitimate transaction type found the failure on its very first attempt at redeeming a customer's entire remaining balance — an ordinary, common, everyday transaction, not an unusual or adversarial one.

What is actually built today

Centriu Loop's balance-update trigger applies every ledger movement through an explicit UPDATE-first sequence, falling back to an INSERT only when no existing balance row is found for that customer.

A customer redeeming their ENTIRE remaining balance — bringing it to precisely zero — is now correctly accepted, since the database's own CHECK constraint is validated against the update's real, final resulting value rather than an isolated, hypothetical proposed row.

The database-level guarantee that a balance can never go negative remains fully in force — the fix corrects how a legitimate exact-balance transaction is APPLIED, not the underlying rule itself.

A genuine race between two truly simultaneous first-ever movements for a brand-new customer is handled by retrying the update once a concurrent insert is detected, preserving correctness without reintroducing the original defect.

This fix was verified against a real PostgreSQL database using the exact transaction type that originally triggered the failure — an ordinary, complete balance redemption — not merely reasoned about from the statement's own source code.

A cashier who checks the wrong drawer before ringing up the sale (illustrative framing of the actual confirmed mechanism)

Before the fix, redeeming an entire $100 balance down to zero was rejected, because the system checked whether "-$100 on its own" was a valid balance — which it is not — rather than checking what the balance would actually become once combined with the $100 already on record. After the fix, the same redemption correctly checks the ACTUAL resulting balance ($100 minus $100, equal to zero) rather than the standalone delta, and succeeds exactly as it should.

What changes operationally

Centriu Loop's balance-update mechanism now applies every ledger movement through an explicit update-then-insert-if-needed sequence, closing a gap where redeeming a customer's entire remaining balance down to exactly zero — an ordinary, common transaction — was wrongly rejected by a non-negative-balance constraint validating an isolated, hypothetical proposed row rather than the transaction's genuine final result.

When this is not the right fit

This automation covers specifically how Centriu Loop's own balance-update mechanism resolves a database conflict correctly under a non-negative-balance constraint. It uses the same general SQL pattern (insert-or-update-on-conflict) this pillar's separate wave 93 Helix rate-limit page and an earlier Axiom quota-counter page both use CORRECTLY, as the FIX for an entirely different problem (a race condition) — this page instead documents a case where that same pattern, combined with a NEW constraint, produced a false rejection, the opposite direction of finding.

One combined statement vs. an explicit update-first sequence

A single "insert, or update on conflict" statement is more compact to write and is entirely correct for the many cases where a constraint being validated does not depend on values already present on an existing row. It becomes incorrect specifically when a constraint's outcome genuinely depends on combining an incoming delta with an existing stored value — because the database validates that constraint against the PROPOSED insert alone, before any conflict is resolved. An explicit update-first sequence, falling back to insert only when nothing exists yet, guarantees every constraint check happens against the row's real, final values in every case — the only version of the two that is correct regardless of what a specific constraint happens to depend on.

Related systems

Main system: Centriu Loop.

What it does NOT do

  • Does not weaken or remove the non-negative-balance guarantee itself — a debit that would genuinely leave a balance negative continues to be correctly rejected; this fix corrects only the one case (an exact, complete redemption) that was wrongly rejected alongside it.
  • Does not affect any OTHER ledger movement type's own correctness — credits, adjustments, expirations, and chargebacks were not affected by this specific gap, which was isolated to how a debit's proposed value interacted with the non-negative check.
  • Does not overlap with this pillar's separate wave 93 Helix rate-limit page or an earlier Axiom quota-counter page — both use the identical general SQL pattern correctly, as the fix for a race condition; this page documents the same pattern producing a false rejection when combined with a new constraint, the opposite direction of finding.
  • Does not reintroduce the original race the combined statement was designed to prevent — a genuine simultaneous-first-movement race for a brand-new customer is handled with a retry, not by reverting to the original approach.
  • Does not extend to any other balance or counter in Centriu's other systems — this fix is specific to Loop's own cashback balance-update trigger, confirmed to have carried this exact gap.

Security and governance

Centriu Loop's balance-update mechanism now applies every ledger movement through an explicit update-then-insert sequence, ensuring every constraint check runs against a transaction's real, final resulting value — closing a gap where redeeming an entire balance down to exactly zero was wrongly rejected. Any personal or financial data referenced in ledger records remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on data handling lives at /governanca and /iso.

Pricing and contracting

Available by monthly subscription, with tiered plans. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).

Frequently asked questions

Could a customer have lost cashback because of this bug?

No — the defect REJECTED a legitimate redemption rather than incorrectly allowing or losing anything; the redemption attempt failed with an error and no balance was altered until the fix corrected the underlying logic.

Why did only an EXACT, full-balance redemption trigger this, and not a partial one?

Because the constraint's failure depended on the raw, standalone delta itself violating the non-negative rule — which only happens when the proposed insert row (carrying just the delta) is itself negative, the exact shape of a full, exact redemption combined with how the balance's own arithmetic works out to precisely zero.

What does PostgreSQL's own execution order have to do with this?

PostgreSQL validates a statement's CHECK constraints against the row it is proposing to INSERT before it determines whether that proposal will instead be redirected into an UPDATE by a conflict. For an existing customer, the real, final write is always the UPDATE — but the constraint was being checked against the doomed, never-actually-written INSERT proposal instead.

Is this the same finding as the Helix rate-limit or Axiom quota-counter pages on this site?

No — both of those pages use the identical general SQL pattern (insert-or-update-on-conflict) CORRECTLY, specifically to close a race condition. This page documents the same pattern, combined with a newly-added constraint, producing a false REJECTION of a legitimate transaction — the opposite kind of finding, in a different system.

How was this actually confirmed as a real, reproducible bug rather than a one-off report?

A real PostgreSQL test battery exercising every legitimate transaction type hit the failure on its very first attempt at an exact, full-balance redemption — an ordinary, common transaction — confirming the defect was structural and reproducible, not incidental.

What does Centriu Loop cost?

It is sold by subscription with a published starting price — exact current values are on the central pricing page.

See how Centriu Loop lets a customer spend every last cent correctly

Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.

Sources

  1. Centriu Loop — public product page — Centriu, 2026-07-20 · link(primária)
  2. Centriu Loop — public factsheet (API, JSON) — Centriu, 2026-07-21 · link
  3. Law No. 13,709/2018 — Brazil’s General Data Protection Law (LGPD) — Presidência da República (Brazil), 2018-08-14 · link

Last material update on .

By · AI-assisted production, with human review