Realtime Update Raw-Payload Stale Display Automation: Nine Screens That Never Actually Refreshed

A live update that arrives in the wrong shape is invisible, not merely delayed
Subscribing directly to a database's own real-time change stream, and merging an incoming row straight into an already-rendered screen's own state, is an efficient, low-latency way to keep a UI current — when the incoming row's field names actually line up with the field names the screen reads. A codebase translating database column names (commonly written in snake_case) into a different naming convention for its own UI-facing models (commonly camelCase) is a completely standard, reasonable practice — but it means a raw database row and a screen's own in-memory record are, structurally, two different shapes describing the same underlying data. Merging one directly into the other adds fields with names the screen has never heard of, while leaving every field the screen actually reads at its previous, stale value — a genuine update event arrives, and the interface changes nothing.
How the underlying problem shows up before you fix it
A real-time subscription handler merges an incoming database row directly into an existing in-memory UI record (`{...item, ...payload.new}`) without first translating the row's own field names into whatever naming convention the UI record actually uses.
A screen's displayed values do not change in response to a genuine database UPDATE affecting the exact row currently shown — the update event fires, a state-setting function runs, and nothing visible happens, because the fields the screen reads were never among the ones the merge actually touched.
The identical mismatch, once introduced in one realtime subscription handler, is easy to replicate across every OTHER subscription in the same file if each one was originally written by copying the same pattern for a different resource — turning one root cause into several outwardly-identical symptoms.
A screen's INITIAL load (a full fetch through a dedicated service function) shows correct, properly-named data, while a SUBSEQUENT realtime update to the same row shows stale data — the discrepancy is specific to the update path, not the underlying data or the initial rendering logic.
This class of defect is easy to miss in ordinary manual testing, because a single person testing alone rarely triggers their own realtime update from a second, independent source at the same time they are looking at the first screen — the gap only becomes visible with two genuinely separate sessions or users interacting with the same data concurrently.
How nine screens that looked live, but weren't, actually became live
Centriu Gauge's own main application component subscribes, on load, to real-time database changes for nine separate financial resource types at once: invoices, payables, suppliers, projects, account categories, cashbox accounts, cashbox transactions, documents, and notifications — a deliberate design meant to keep every open screen showing genuinely current data without requiring anyone to manually refresh.
For each of those nine subscriptions, before this fix, an incoming UPDATE event was handled with a pattern repeated nine times, once per resource: `setInvoices(prev => prev.map(item => item.id === payload.new.id ? { ...item, ...payload.new } : item))`, and the equivalent for each of the other eight resources. `payload.new` is the raw database row exactly as Supabase's own realtime feed delivers it — meaning its field names are the database's own real column names, typically written in snake_case (`due_date`, `total_amount`, `supplier_id`, and so on for each resource's own specific columns). The screen's own in-memory record for that same resource, by contrast, uses camelCase field names (`dueDate`, `totalAmount`, `supplierId`) — the convention the rest of the screen's own rendering code, filtering logic and formatting functions all actually read from.
Spreading `payload.new` directly on top of the existing camelCase record adds every one of the database's own snake_case field names onto the object, as entirely new, previously-nonexistent properties — `item.due_date` now exists alongside `item.dueDate`, for example, with `item.dueDate` retaining whatever value it had BEFORE this specific update ever arrived. Every field the screen's own rendering code actually reads — because it reads the camelCase name — continues to display its old, pre-update value, indefinitely, for as long as the screen stays open. A colleague changing an invoice's due date, a webhook marking a payable as reconciled, or any other legitimate update landing through this exact real-time path would be completely invisible on an already-open screen for any of the nine affected resource types — not delayed, not partially shown, simply absent from what a person looking at the screen could see, until they manually reloaded the entire page.
The fix replaces the direct-merge pattern for UPDATE events (and unifies it with the handling already used for INSERT events, since both need the identical correction) with a call to the SAME resource-specific service function each screen already calls for its own initial data load — `invoiceService.getAll()`, `payableService.getAll()`, and the equivalent for each of the other seven resources. Those service functions already contain the correct, already-proven translation from the database's real column names into the camelCase shape the screen actually uses, because they are the exact functions responsible for the screen's own first, correct render. Rather than attempting to hand-translate each of nine different payload shapes inline inside nine separate realtime handlers — a change that would need to be kept correct nine separate times, and re-verified every time any one of the nine resources' own database schema changes — the fix simply asks each resource for its own current, correctly-shaped full list again whenever an insert or update notification arrives, reusing logic that already had to be correct for the page to have ever worked at all.
What is actually built today
Centriu Gauge's real-time subscriptions for all nine financial resource types (invoices, payables, suppliers, projects, categories, cashbox accounts, cashbox transactions, documents, notifications) refetch through each resource's own dedicated mapping service on both INSERT and UPDATE events.
Every field a screen actually displays is guaranteed to reflect a genuine database change, because the refetch reuses the identical, already-correct translation logic responsible for the screen's own initial, known-correct load.
A change made in one browser tab, by a different teammate, or by an automated backend process now appears on an already-open Gauge screen without requiring a manual page reload, across all nine affected resource types.
DELETE events, which were already handled correctly before this fix (filtering the in-memory list by ID rather than merging a payload), were confirmed unaffected and left unchanged.
The fix required no change to what real-time events Centriu Gauge subscribes to, or to the underlying database schema — only to how an INSERT or UPDATE notification is translated into an actual on-screen update.
An invoice edited by a colleague, invisible on your own open screen (illustrative framing of the actual measured finding)
Before the fix, one team member updating an invoice's due date inside Centriu Gauge — from any device, at any moment — would leave a second team member's already-open invoices screen completely unaware anything had changed: the realtime event fired, the screen's own update handler ran, and the specific field displayed on screen (`dueDate`) never received the new value, because the merge added the database's own `due_date` field under a different name entirely. The second team member would need to manually reload the page to see the actual, current due date. After the fix, the identical edit refetches the full, correctly-mapped invoice list the moment the update event arrives, and the second team member's screen reflects the real, current due date without any manual action.
What changes operationally
Centriu Gauge's real-time updates across all nine subscribed financial resource types now genuinely refresh what an already-open screen displays, closing a gap where a database UPDATE event fired correctly but never actually changed anything a person could see, because the raw database payload's field names never matched the screen's own display fields.
When this is not the right fit
This automation governs Centriu Gauge's own internal real-time-update handling for the nine financial resource types it subscribes to — it does not add a new real-time feature or change what triggers a realtime event in the first place, and DELETE events, already handled correctly, were unaffected and untouched by this fix.
Merging a raw payload directly vs. refetching through the existing translation layer
Merging an incoming real-time payload directly into existing state is the lower-latency approach in principle — no extra round-trip to the database is needed, only the fields that actually changed are touched. That approach is only correct when the incoming payload's own field names genuinely match the shape the UI expects, which was not the case here across all nine resources. Refetching through each resource's own existing, already-correct mapping service costs one additional request per update event, but guarantees the screen always reflects a properly-translated, currently-accurate record — reusing logic that already had to be correct for the screen to ever have worked in the first place, rather than requiring nine separate inline translations to be written and kept correct independently.
Related systems
Main system: Centriu Gauge.
What it does NOT do
- Does not add a new real-time feature to Centriu Gauge, or change which nine resource types are subscribed to — this fix corrects only how an already-existing INSERT or UPDATE notification is translated into an actual on-screen refresh.
- Does not affect DELETE event handling, which already filtered the in-memory list correctly by ID before this fix and required no change.
- Does not retroactively refresh a screen that was already open and already showing stale data before this fix was deployed — a person with an already-open Gauge screen from before the deploy would need one manual reload to pick up the corrected behavior going forward.
- Does not change the underlying database schema, column names, or realtime event configuration in any way — the fix is scoped entirely to the client-side handler translating an incoming event into a screen update.
- Does not overlap with this pillar's separate finding about Centriu Gauge's own proof-of-payment persistence gap — that is covered on its own companion page and is an unrelated mechanism in a different part of the product.
Security and governance
Centriu Gauge's real-time update handling across all nine subscribed financial resource types now correctly reflects genuine database changes on an already-open screen, closing a gap where a legitimate update could arrive and be silently absorbed without ever reaching what a person actually sees. Full detail on access control and audit trails lives at /governanca and /iso.
Pricing and contracting
Available by custom proposal, arranged directly with the team. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).
Frequently asked questions
Did this cause incorrect financial data to be stored anywhere?
No — the underlying data in the database was always correct. The defect was specific to the SCREEN's own in-memory display failing to reflect a genuine update in real time, not to what was actually saved.
Why didn't this show up as an obvious visual glitch?
Because the merge added extra, unused fields with the database's own raw names rather than producing an error — the screen simply kept displaying its previous values for the fields it actually reads, with nothing visibly broken about the display itself.
Was every resource type affected equally?
Yes — the identical merge pattern was used for all nine subscribed resource types (invoices, payables, suppliers, projects, categories, cashbox accounts, cashbox transactions, documents, notifications), so all nine shared the same defect on UPDATE events.
Were INSERT events also affected?
The specific defect described here was in the UPDATE handling; the fix unifies INSERT and UPDATE to both refetch through the same correct mapping service, so both are now handled identically and correctly.
Does a person need to do anything to see the fix take effect?
A screen that was already open before the fix was deployed would need one manual reload; any screen opened after the deploy reflects the corrected real-time behavior automatically from that point forward.
What does Centriu Gauge cost?
It is sold by subscription with a published starting price — exact current values are on the central pricing page.
See how Centriu Gauge keeps every open screen genuinely current
Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.
