All writing
Published

Performance

Anatomy of a 91% Speedup: Implementing Data Row Patching in Enterprise Web Apps

A practical breakdown of how targeted row updates beat full-list refreshes in dense enterprise tools — the exact architecture behind the 80s to 7s speedup.

·

9 min read

PerformanceReactRow Patching

An 80-second load time is not a performance issue. It's an existential one. Users of enterprise tools — the people managing commitments, prime contracts, and budgets for companies like Target, Skanska, and AECOM — don't have patience for a spinner that outlasts their coffee. This is the story of how we took a list view from 80 seconds to 7 seconds, and the pattern that made it repeatable.

The problem: full-list refresh as the default

The application rendered dense data grids — hundreds of rows, dozens of columns, calculated fields, status badges, and nested relationships. Every time something changed — a status update, an inline edit, a background sync — the entire list was refetched and re-rendered. The server query was expensive, the payload was large, and the React reconciliation was heavy.

The instinctive fix is to optimize the query, compress the payload, or virtualize the rendering. All worth doing, but none addresses the core inefficiency: we were refetching data we already had.

Row patching: the core idea

Row patching is a targeted update strategy. Instead of refetching the full list when a single row changes, you fetch only the affected row — or just the changed fields — and merge it into the existing client-side collection. The grid re-renders one row, not a thousand.

The fastest query is the one you never make. The fastest render is the one you never perform.

The architecture

1. A normalized client-side store

List data was stored in a normalized map keyed by entity ID, not as a flat array. This made lookups O(1) and meant a patch was a simple merge — find the row, spread the updated fields, trigger a re-render for just that row's cell.

2. Targeted patch endpoints

We added server endpoints that returned a single row's updated state after a mutation. An inline edit on row 47 sent a PATCH and received back the recalculated row — including server-side computed fields like totals and statuses — without touching the other 499 rows.

3. Granular re-rendering

With AG Grid, we leveraged row transaction updates — refreshing individual row nodes instead of resetting the entire row model. Combined with React's rendering model, this meant the DOM diff was tiny: one row's worth of cells.

The results

  • Initial list load: 80s → 7s (91% reduction) by combining query optimization, payload reduction, and smarter rendering.
  • Post-edit refresh: effectively instant — no full refetch, no spinner, no scroll position loss.

Generalizing the pattern

Row patching isn't specific to AG Grid or to enterprise tools. The principle — update only what changed, store data in a shape that makes targeted updates trivial, and reserve full refreshes for when they're actually needed — applies anywhere you have list views with frequent, localized mutations. It's one of the highest-leverage performance patterns I've implemented, and once you internalize it, you start seeing full-list refreshes as the anti-pattern they often are.


Previous

Preparing Frontend Ecosystems for Compliance: A FedRAMP Playbook

Next

Architecting Micro-Frontends at Scale: Module Federation in Angular vs. React


  • Home
  • Writing
  • Lab
  • Resume
  • GitHub
  • LinkedIn
  • X
  • ahmed@aashrafh.me

Open to relocation for Senior+/Lead opportunities

© Ahmed Ashraf