Six months into a dashboard build, someone asks a question that should be trivial: is this balance current?
Not because anything is broken. Because the balance card, the transaction list and the FX panel were built by three people at three different times, and each one arrived at its own private theory about how old data is allowed to be before it stops being useful. One refetches on focus. One polls every thirty seconds because that felt about right. One caches until you hard-refresh. Nobody wrote any of it down, so nobody can tell you which is correct — and now the question "is this number current" has three answers depending on where you look.
I've built frontends for banks — NatWest, US Bank, TIAA-Nuveen — and this is the failure I've watched happen most often. It isn't a coding failure. It's a sequencing failure: the team designed the component tree first and treated data freshness as an implementation detail to be settled per widget, per ticket, by whoever picked it up.
It's backwards. Freshness is a contract, and it belongs upstream of the architecture — because what you decide there determines your transport, your caching, your error states, and the shape of the boxes themselves.
This is how I'd approach a banking dashboard, in the order the decisions actually have to be made.
The short version. Six decisions, in dependency order: who the user is → the freshness contract → architecture boundaries → where state lives → failure design → what you measure. Most teams start at boundaries and retrofit freshness per widget. That's the mistake this article is about.
Worth establishing first, because most system design writing is backend writing, and the vocabulary we borrow doesn't fit.
Backend system design is mostly about scale under load. How do we store this, replicate it, keep it consistent, and not fall over at ten times the traffic?
Frontend system design is mostly about uncertainty at the edge. The data you're holding is already slightly out of date. The network will drop at the worst possible moment. The user is a real human who will click the button twice because nothing visibly happened. And the whole screen has to stay usable when a third of it is broken.
The backend designs the warehouse. The frontend designs the shop floor — where actual people, with actual confusion and actual patchy 4G, are trying to get something done.
Accessibility sitting in that right-hand column is not decoration. In this domain it's a legal requirement, and it has architectural consequences I'll come back to.
Each decision narrows the next. Make them out of order and you spend the following year retrofitting.
The one that matters most is the placement of the freshness contract at number two — above the boundaries, above state, above everything structural. That's the inversion this whole piece argues for, and the rest of it is the argument.
"Banking dashboard" is not a specification. It could mean a retail customer checking whether their salary landed, or an operations analyst reconciling four hundred payments before a cut-off.
Those are not the same product. The first needs to be fast and legible on a phone at a bus stop. The second needs dense tables, keyboard-first navigation, and to stay responsive at ten thousand rows. Almost every number further down this article changes depending on which one you're building.
Nobody volunteers this. It arrives as an assumption inside a ticket, and if you don't surface it early you find out during UAT. For the rest of this piece I'm assuming retail with some business banking.
Then there's the second list — the one that never makes it into a ticket at all.
The left column is what the product manager asks for. The right column is what the compliance officer assumes is already true, because to them it simply is how the world works. Freshness guarantees. Role-based visibility. An audit trail of what a customer was shown at 14:32 when they later dispute what they saw. A session timeout policy you don't own and can't negotiate.
