Frontend & Backend Modernization × Data-Heavy B2B

Frontend modernization for data-heavy B2B teams

Query builders, virtualised grids, and large-dataset charts that stay responsive when the result set is a million rows.

Domain context

Data-product frontends break in ways marketing dashboards never do. A grid that re-renders from scratch every time a user reorders a column is unusable at 200 columns. A chart library that ships every point to the DOM falls over at 100,000 rows, never mind a million. A query builder that round-trips on every keystroke punishes the analyst who actually knows what they want. A saved view that doesn't survive a schema change quietly loses customer trust the first time a column gets renamed. We rebuild these surfaces assuming the data is large, the user is sophisticated, and the screen will be open for the whole working day. Performance budgets get framed in milliseconds-per-keystroke, not page-weight kilobytes. The first thing we measure on most engagements is keystroke-to-paint, because that's the number the analyst feels.

Why this combination

Most modernization shops will hand back a faster build pipeline and a cleaner component library. Data-product modernization needs more. It needs a virtualisation strategy that survives column reorder, freeze, resize, and hide without losing scroll position. It needs a charting layer that downsamples on the client cleanly so a million-point time series renders without dropping interaction. It needs a query-builder UX an analyst can actually fall in love with: keyboard-first, schema-aware, with a previewable result count before they hit run. None of this comes out of a framework. It comes from engineers who've shipped these surfaces before and know which abstractions break first.

“We rebuilt a 240-column saved-views grid that had become unusable above 50k rows. The new surface holds 60fps scroll and column reorder at 2M rows on the analyst's laptop, with per-user view persistence.”
Vertical analytics platform serving operations teams. The original grid was an off-the-shelf component wrapped in Redux; every column resize triggered a full re-render of the visible viewport. The rebuild used a virtualised core with windowed columns, a separate render layer for sticky and frozen columns, and a per-user view-state store keyed on schema version, so saved views survive column renames. · Grid scroll: 12fps → 60fps at 2M rows · View load: 4.2s → 280ms

Frequently asked

How does Hotreloads decide between a third-party data grid and building one in-house?
We start with the third-party. AG Grid, TanStack Table, and Glide Data Grid each cover the common 80% well. The decision to roll our own only comes when there's a specific behaviour the customer cares about, usually around column-level interactions, custom cell rendering at scale, or a peculiar permission model, that the off-the-shelf component can't do without forking. We document the trade-off explicitly before writing a line of grid code.
What is Hotreloads' approach to charting libraries when datasets are very large?
We default to a canvas-based renderer (uPlot, ECharts, Plot with the right config) and treat downsampling as a first-class layer, not a hack. The client receives a downsampled series matched to viewport width, with the option to request raw points on zoom. SVG-based libraries get vetoed for any series above ~5,000 points. The DOM isn't the right primitive for analytical charts at scale.
How does Hotreloads build query-builder UIs that analysts actually like?
Keyboard first. Schema-aware autocomplete that matches IDE expectations. A live result-count preview before the user commits to running the query, so they can iterate without waiting for the warehouse. Saved queries that survive schema evolution. The opinionated bit: we don't try to hide SQL. Analysts who use these tools all day know SQL, and the right interface meets them there rather than translating to a lossy visual builder.
How does Hotreloads handle row-level security and column masking in the UI?
Permissions are enforced server-side, but the UI has to surface them coherently. Masked columns show a deliberate placeholder rather than an error. Restricted rows are filtered with a count of how many were hidden. Saved views remember the permission context they were created in. We work with the backend team to ensure the permission decision flows through to the client as structured metadata, not just as a 403.
What about saved-view persistence and dashboard sharing across schema changes?
Saved views and shared dashboards are versioned against the schema they were authored on. When a column is renamed or removed, views that reference it are marked as needing migration rather than silently breaking. The user sees a clear notice with a one-click remap to the new column. Sharing a dashboard captures the schema version, so a colleague opening the link sees the same numbers the author did, even months later.