DEV Community

kirandeepjassal-crypto
kirandeepjassal-crypto

Posted on Originally published at prepstack.co.in

Optimizing Large Data Grids in React — Server Pagination, Infinite Scroll, Virtual Scrolling, AG Grid, TanStack Table (Real Code + Metrics)

Every React app eventually has to show 50,000 rows of something — transactions, audit logs, leads, orders, sensor readings. And every team eventually discovers that React's "just .map() over the array" advice doesn't scale past about 5,000. At 50,000 the page locks for 14 seconds, scrolling is 8fps, and the tab burns 1.2 GB.

This is a condensed walkthrough. I took a real 250,000-row fintech transactions dashboard and benchmarked every relevant technique on the same dataset (TTI, scroll FPS, INP, DOM nodes, memory). The full guide with all the code, the complete comparison matrix, the decision flow, and the production architecture is on my site 👇

Full guide: https://prepstack.co.in/blog/react-large-data-grids-optimization-pagination-virtual-scroll-ag-grid-tanstack-guide

Why naive rendering breaks

rows.map(r => <tr>…</tr>) over 250k rows breaks in order: reconciliation diffs all 250k elements (~3–5s of main-thread work), the DOM balloons to ~750k nodes, every row holds a fiber + listeners (1+ GB), and TTI shoots past 10 seconds. The fix isn't one technique — it's the right technique for your data shape and UX.

The five techniques, same 250k-row dataset (4× CPU throttle)

1. Server-side pagination — the cheapest 10× you'll ever get. Only ship what the user can see; run filters/sorts on the server. Use cursor pagination, not offset — at row 50,000, OFFSET 50000 makes the DB walk 50k rows it then throws away. Alone: TTI 14.2s → 0.8s, memory 1.2 GB → 95 MB. If you do nothing else, do this.

2. Infinite scroll — a UX choice, not a perf one. Right for feeds/consumption; wrong for audit/analyst grids where users need page numbers, jump-to-row, and shareable URLs. And it's a trap without virtualization — after 100 pages the DOM hits 15,000+ nodes and FPS drops to 22.

3. Virtual scrolling — the biggest client-side win. Render only the ~30 rows the user can see; the container lies about being tall enough for all 250k. DOM nodes 750k → ~120, FPS 8 → 60. But it doesn't fix memory if the data's still in JS — pair it with pagination.

4. AG Grid — the enterprise default. Need grouping, pivots, master-detail, Excel-like editing, server-side row model? AG Grid gives it all out of the box (Community is free/MIT and excellent). Cost: ~270 KB gzipped and opinionated theming.

5. TanStack Table — headless, write your own DOM. It owns sort/filter/paginate state; you render the markup. Pair with @tanstack/react-virtual and you get an AG-Grid-fast custom grid for ~+20 KB. The right pick for a design system.

The comparison, at a glance

Metric Naive Server pagination Virtual only AG Grid SSRM TanStack + Virtual
TTI 14.2s 0.8s 1.4s 0.5s 0.7s
Scroll FPS 8 60 60 60 60
DOM nodes 750k 250 ~120 ~200 ~140
Memory 1.2 GB 95 MB 380 MB 110 MB 90 MB
Bundle 0 0 +6 KB +270 KB +20 KB

What we actually shipped

Server cursor pagination + virtual scrolling + TanStack Table (headless) for the design system. Same fintech app: 14.2s → 0.6s TTI · 8 → 60fps · 1.2 GB → 110 MB, and "the grid is slow" support tickets went 14/month → 0.

The mental model

The answer to "show me 250,000 rows" is almost never a single library — it's a combination. Server pagination first, always. Virtualize when any page renders more than ~200 rows. Then pick the library by feature need, not vibes. Do that and "make the table faster" stops being a recurring ticket and becomes a one-time architecture choice.

The full guide has the real code for all five techniques (TanStack Query cursor pagination, IntersectionObserver infinite scroll, @tanstack/react-virtual, AG Grid server-side row model, TanStack Table), the full matrix, the decision flow, and the production architecture diagram:

https://prepstack.co.in/blog/react-large-data-grids-optimization-pagination-virtual-scroll-ag-grid-tanstack-guide

Originally published on PrepStack.

Top comments (0)