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
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.
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
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
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
overscanRowsto 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.