Million Rows Performance

Work with very large row counts using virtual scrolling and backend loading.

This example shows the shape of a large-grid setup. The demo uses 100,000 generated rows in memory; production apps should validate their own limits and usually prefer backend loading for million-row datasets.

100,000 rows | Virtual scrolling active

In-Memory Large Grid

large-grid.ts
import { Grid, type ColumnDef } from '@zengrid/core';
import '@zengrid/core/dist/styles.css';
const rowCount = 100_000;
const columns: ColumnDef[] = [
{ field: 'id', header: 'ID', width: 80 },
{ field: 'name', header: 'Name', width: 200 },
{ field: 'email', header: 'Email', width: 260 },
{ field: 'department', header: 'Department', width: 150 },
{ field: 'salary', header: 'Salary', width: 120 },
];
const rows = Array.from({ length: rowCount }, (_, row) => [
row + 1,
`Employee ${row + 1}`,
`employee${row + 1}@company.com`,
['Engineering', 'Sales', 'Marketing', 'HR', 'Finance'][row % 5],
50000 + ((row * 137) % 100000),
]);
const grid = new Grid(document.getElementById('grid')!, {
columns,
rowCount,
colCount: columns.length,
rowHeight: 36,
colWidth: columns.map((column) => column.width ?? 140),
overscanRows: 10,
overscanCols: 3,
enableCellPooling: true,
});
grid.setData(rows);
grid.render();
Info

Virtual scrolling keeps the DOM focused on the visible viewport. Memory usage still depends on how much row data you hold in JavaScript.

Backend Loading For Million-Row Data

Use backend mode when row data should be requested on demand.

backend-large-grid.ts
const grid = new Grid(document.getElementById('grid')!, {
columns,
rowCount: 1_000_000,
colCount: columns.length,
rowHeight: 36,
colWidth: columns.map((column) => column.width ?? 140),
dataMode: 'backend',
onDataRequest: async ({ startRow, endRow, query, signal }) => {
const response = await fetch('/api/employees/window', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
signal,
body: JSON.stringify({ startRow, endRow, query }),
});
return response.json();
},
});
grid.render();
navigation.ts
grid.scroll.toCell(0, 0);
grid.scroll.toCell(500_000, 0);
grid.scroll.toCell(999_999, 0);
const position = grid.scroll.getPosition();
const visibleRange = grid.scroll.getVisibleRange();

Performance Checks

stats.ts
const stats = grid.getStats();
console.log(stats);
grid.on('scroll', ({ scrollTop, visibleRange }) => {
console.log(scrollTop, visibleRange);
});

Practical Guidance

  • Keep renderers simple in large grids.
  • Use overscanRows to reduce blanking during fast scrolls, then tune it with real devices.
  • Use backend mode when the dataset is too large to hold comfortably in memory.
  • Avoid doing expensive work inside scroll handlers.
  • Test sorting and filtering with the same data mode you will use in production.
Warning

Do not assume a million-row demo proves production readiness for your app. Validate the real row shape, renderers, editors, filters, devices, and browser matrix.

Next Steps