‹ Build a Dashboard Lesson 3 of 16
Contents Lesson 3 of 16

4 min read · professional

One data layer for three panels

Two panels want AAPL. Fetched independently that is two requests for one fact, and this lesson is the piece of architecture that makes it one.

The price list, and why it decides the design

From course 1, measured 2026-08-26:

Endpoint Calls per request
/user 0
/eod and friends 1, whatever the row count
/real-time 1 per symbol
/screener, /news, /technical 5
/fundamentals 10

A cockpit multiplies whatever you get wrong here. Three panels each fetching their own quotes for an overlapping set of ten symbols is thirty calls where fourteen distinct symbols would have cost fourteen.

A request cache with one owner

One module owns fetching. Panels ask it for symbols; they never call the proxy themselves.

const quotes = await marketStore.quotes(["AAPL.US", "MSFT.US"]);

Three responsibilities, and each removes a class of bug:

Deduplicate within a tick. Collect every symbol asked for in the same frame, issue one request, hand the same rows to every caller. Two panels asking for AAPL simultaneously produce one fetch.

Cache with an explicit age. Store {rows, fetchedAt} and let panels ask how old it is. Never cache without recording when — a cache with no age is how a dashboard shows Tuesday's prices on Wednesday and looks fine doing it.

Share the in-flight promise. If a fetch for AAPL is already running, a second asker gets the same promise rather than a second request. Six lines, and it is what stops a re-render storm becoming a quota event.

One snapshot, one timestamp

Here is a fixture from a live multi-symbol response:

[{"code":"AAPL.US","timestamp":1787689680,"close":309.90},
 {"code":"MSFT.US","timestamp":1787689680,"close":491.71},
 {"code":"TSLA.US","timestamp":1787689740,"close":350.25}]

Two rows at 20:28:00 UTC and one at 20:29:00 — sixty seconds apart in the same response. The API is not being inconsistent; those are the last trades it had for each symbol, and thinly traded instruments are much further behind than a minute.

So a dashboard header reading "as of now" is false. Show the oldest timestamp in the set, because a cockpit is only as current as its stalest panel, and that is the number a person needs before acting.

Panels do not fetch

The rule that makes all of this hold: a panel receives data, it does not go and get it. A panel that fetches is a panel that cannot be reused, cannot be tested without a network, and will eventually duplicate a request some other panel already made.

This is the same boundary discipline as the transport layer in course 2, one level up.

Try it now

Count the distinct symbols your three panels want on a typical view, then count the requests they currently make. The gap is what the data layer buys you, and it is usually two to three times.