A grid that keeps up with the feed
The screen your payments team watches all day is fed from somewhere that does not slow down for them. Authorisations arrive continuously across twenty thousand merchant corridors, and the grid they are watching has two jobs: show the current state of every one of them, and stay usable while it does.
Most grids do the first and give up the second. The rows update, and the scroll bar fights you, and selecting something takes two attempts because the row moved between the press and the release. The grid above is taking a feed at full rate right now. Scroll it while you read this. It should not feel like anything.
The rate under the grid is yours, not ours
Underneath the grid is a line that says how many rows a second the browser actually wrote. It is measured in the tab you are reading this in, over a rolling three second window, and it is derived from the grid’s own counters rather than from ours: rows written is rows handed over, less the ones merging removed, less the ones still waiting. Every term in that comes from the grid, so the number cannot flatter us by counting the same row twice.
The feed asks for six thousand rows a second, as thirty rows every five milliseconds. The grid wrote between three and a half and six thousand rows a second, and that range is what the page printed back at us while we watched it. Yours will be different, which is the entire reason for measuring it where you are rather than quoting it from where we are.
Forty updates to one row are one row of work
The reason any of this is affordable is that the grid does not treat a message as a unit of work. It treats a row as one.
Traffic on a real authorisation feed is not spread evenly, and the demo’s is not either: a handful of merchants carry most of it and the long tail moves once a minute. A busy corridor therefore gets touched several times between one paint and the next, and every one of those messages says the same kind of thing. The authorisation count went up. The latency moved. The approval rate is now this. Only the last one is still true when the frame arrives.
So changes are collected and merged by row key between paints, and the grid writes each affected row once. The counter under the grid that says how many were merged away before they were painted is that saving, made visible: those are updates the grid never had to paint, on rows where painting them would have been overwritten a few milliseconds later anyway.
That is also what keeps the interaction alive. Painting happens once per frame, on a budget, and a flush that runs past its budget hands the remainder back and finishes on the next frame instead of blowing through the one it is in. Your scroll gets its frame. Your selection survives, because rows are identified by key rather than by position, so an update landing on row four hundred does not disturb the row you had picked.
The alternative, which is what you get from a grid that was handed a fresh array of rows and re-rendered, is a repaint for every message including the ones that were about to be overwritten.
What this is worth to the person watching it
For the analyst, the answer is that the numbers on their screen are the current numbers and they can still use the screen. They can sort by latency while it is running and the sort stays correct as rows move through it. They can filter to one acquirer and the feed keeps flowing into the filtered view. They can watch the state column flick from ok to slow to degraded and trust it, because the highlight on a changed cell means that cell genuinely changed rather than that the row was redrawn.
For you, the answer is that none of that was a project. There is no debounce you tuned, no requestAnimationFrame loop you wrote, no ring buffer, no “we turn off the live updates when the user is scrolling” compromise that somebody will eventually file a bug about.
Leave the grid above running for a minute, then scroll it and sort it and see whether the rate under it moves.
See the same feed with a pause control or read how the update queue is configured.