In this chapter
We'll prove, with a real script, that a database write can succeed perfectly while another client's view goes stale — the real incident behind this Act's opening — and meet Backend-as-a-Service and realtime databases as the response built specifically to close that gap.
The Problem in Real Life
A driver marks order #4471 "Out for Delivery." A support agent, on the phone with the same customer a minute later, is still looking at "Delivered" — from an hour ago, a different order entirely, still sitting on her screen because nothing told her it had changed.
Sarah checks the database directly. The record is correct. It says exactly what the driver just wrote. The support agent's screen just... doesn't know that yet.
The data's right. Her screen just hasn't heard about it.
Sarah
Wrong Data vs. Stale Data
The write was correct. The read was stale.
Verified: a client's cached read stays old even after a genuinely successful write elsewhere — not a bug, a gap.
Backend-as-a-Service closes the gap
A BaaS (like Firestore) pushes changes to connected clients, instead of clients guessing when to re-ask.
Client-driven access is the root cause
"Ask when you think you need to" always leaves a window between a real change and a client learning about it.
Same document shape, a different question
The order is still a document, unchanged from Act 2 — what's new is who finds out when it changes, and when.
The Problem Isn't Storage, It's Sync
This is the real distinction this whole Act is built around: the database was never wrong. A set() genuinely, correctly wrote the new value. The problem is that nothing told the other screen looking at that same data — it just kept showing whatever it last happened to fetch, with no way to know a fresher answer now exists.
A Backend-as-a-Service (BaaS) — Google's Firestore is the real, common example — is built specifically to close this gap. Instead of an app manually re-asking "has this changed?" over and over, a BaaS-style realtime database can tell connected clients the moment something actually does change.
clientA's first write succeeds, and clientB's first .get() correctly reads it. Then clientA writes again — a real, successful update, "Delivered." clientB's second .get() still returns "Out for Delivery": the old value, served from its own local cache, because nothing pushed the new one to it. The write was never wrong. clientB's own view simply went stale the moment clientA's second write happened.
clientA.set("orders/4471/status", "Out for Delivery")clientB.get("orders/4471/status")clientA.set("orders/4471/status", "Delivered")clientB.get("orders/4471/status")
This is exactly Mike's incident from this Act's own opening — proven here with a real, runnable script, not just described.
Client-driven data access — the older pattern, where an app decides when to ask for fresh data — is what actually created this gap. It's not that anyone made a mistake; it's that "ask when you think you need to" always leaves a window where the client's view can be behind the database's real, current state. A realtime, subscription-based system flips who's responsible: instead of the client guessing when to ask, the database itself pushes the update the moment it happens — exactly what the next chapter builds.
Document-based modelling carries over from Act 2 mostly unchanged here — GreenMart's order is still a document, orders/4471, with fields like status. What's different in this Act isn't how the data is shaped; it's what happens the instant that shape changes, and who finds out about it, and when.
Key Takeaway
Sometimes the database isn't just where the backend stores data — it becomes part of how the application communicates with the data. The support agent's stale screen isn't a storage bug; it's proof that storing data correctly and keeping every view of it current are two genuinely different problems.
Why This Matters
Every remaining chapter in this Act is really one response to this exact gap — realtime listeners close it while both sides are online, optimistic UI and offline handling close it (with a real conflict to resolve) when one side genuinely can't be reached for a while.
GreenMart now has real, verified proof that a correct write can still leave another screen stale — not a bug, a structural gap client-driven access always leaves open. Closing that gap without making every screen ask constantly is exactly where the next chapter goes.
