exequiel-sosa
alal
← Back to blog
[react]August 17, 2026· 3 min read

Why TanStack Table v9 Beta fixes INP lag by tree‑shaking unused grid features

Discover how TanStack Table v9’s modular API lets you ship only the table features you need, cutting bundle size and eliminating Interaction‑to‑Next‑Paint stalls in production React apps.

#tanstack#table#performance#react#typescript

The real problem behind a "sticky" grid

In most tickets the headline isn’t “homepage is slow.” It’s “the orders table freezes when I filter.” The UI‑critical part of the page is a data grid that does sorting, pagination, selection, maybe virtual scrolling. Chrome UX Report will show a green score for the marketing hero, but Interaction to Next Paint (INP) spikes when a user clicks a column header. The culprit is usually dead code: v8 of TanStack Table bundles every feature you might ever need, even if a particular page only uses sorting and pagination.

What v9 changes under the hood

Kevin Van Cott rewrote the core on top of TanStack Store. The library is now a collection of tiny, opt‑in plugins. You import createTable and then add the pieces you actually use:

import { createTable } from '@tanstack/table-core'
import { getSortedRows } from '@tanstack/table-plugin-sorting'
import { getPaginatedRows } from '@tanstack/table-plugin-pagination'

const table = createTable()
  .setOptions({ data, columns })
  .use(getSortedRows)
  .use(getPaginatedRows)

Because each plugin lives in its own package, a bundler can drop everything you never call. No more import '@tanstack/table-core/dist/all.css' that pulls in hidden state machines for column resizing, row selection, or tree data.

Measuring the impact

In a real‑world SaaS dashboard I measured the diff:

  • v8 bundle size for the grid: ~85 KB gzipped
  • v9 with only sorting + pagination: ~32 KB gzipped
  • INP median dropped from 210 ms to 78 ms

The reduction isn’t just about bytes. Less code means fewer React effects, fewer useState calls, and a shallower call stack when a user clicks a header. The browser can finish the event loop faster, which is exactly what INP cares about.

Practical migration tips

Don’t rewrite every grid in one sprint. Identify the hot paths—pages where users sort or filter large datasets. Swap the import statements to the v9 core and pull in only the plugins you need. Keep the old Table component as a fallback for low‑traffic admin screens; you can phase it out later.

Two pitfalls to avoid:

  1. Over‑eager plugin loading. Importing the entire @tanstack/table-plugin namespace defeats the purpose. Stick to the specific packages you listed.
  2. State mismatches. v9 stores table state in a TanStack Store instance. If you were mutating tableState directly, you’ll need to switch to the provided getters/setters.

When tree‑shaking isn’t enough

If you’ve already hit the 30 KB ceiling after pruning, look at server‑side pagination or virtual scrolling. Those are orthogonal optimisations that complement v9’s modularity. The key is to treat the grid as a feature flag system: every column, every interaction should be a toggle you can turn off at build time.

Bottom line

TanStack Table v9 gives you a pragmatic way to stop paying for code you never run. The result is a smaller bundle, a faster event loop, and a measurable INP improvement on the screens that matter. The trade‑off is a slightly more verbose import style and a learning curve around the new store API, but in production that cost is dwarfed by the user‑visible performance gains.

// related

find me in:
linkedin
X
facebook