· 8 min read

Blazor DataGrid with Virtual Scrolling — Handle 100K+ Rows at 60fps

Render 100,000+ rows in a Blazor DataGrid with virtual scrolling at 60fps. Zero lag, smooth scrolling, configurable overscan. Part of Arcadia Controls Pro ($299/dev/year).

blazorvirtual scrollingdatagridperformancevirtualizec#

Blazor DataGrid with Virtual Scrolling — Handle 100K+ Rows at 60fps

Loading 100,000 rows into a Blazor DataGrid without virtual scrolling will freeze the browser. The DOM can’t handle that many elements, and Blazor’s diffing engine chokes on the render tree. Arcadia DataGrid solves this with true virtual scrolling — only the visible rows exist in the DOM, giving you smooth 60fps performance regardless of dataset size.

Why Standard Blazor Grids Struggle

Blazor’s built-in <Virtualize> component is great for simple lists, but it wasn’t designed for data grids. It doesn’t handle:

Arcadia DataGrid uses AG Grid’s proven virtualization engine under the hood, exposed through a clean Blazor API.

Quick Start

dotnet add package Arcadia.DataGrid
dotnet add package Arcadia.Theme

Add CSS to your App.razor:

<link href="_content/Arcadia.Theme/css/arcadia.css" rel="stylesheet" />
<link href="_content/Arcadia.DataGrid/css/arcadia-datagrid.css" rel="stylesheet" />

Enable Virtual Scrolling

@using Arcadia.DataGrid.Components

<ArcadiaDataGrid TItem="LogEntry"
                 Items="@logEntries"
                 VirtualizeRows="true"
                 Height="600px"
                 ItemSize="40"
                 OverscanCount="10"
                 Sortable="true"
                 Filterable="true">
    <ArcadiaGridColumn Field="@nameof(LogEntry.Timestamp)" Header="Time" Format="G" Width="200" />
    <ArcadiaGridColumn Field="@nameof(LogEntry.Level)" Header="Level" Width="100" />
    <ArcadiaGridColumn Field="@nameof(LogEntry.Source)" Header="Source" Width="200" />
    <ArcadiaGridColumn Field="@nameof(LogEntry.Message)" Header="Message" />
</ArcadiaDataGrid>

@code {
    private List<LogEntry> logEntries = new();

    protected override async Task OnInitializedAsync()
    {
        // Load 100K+ rows — the grid handles it
        logEntries = await LogService.GetAllEntriesAsync();
    }
}

Key parameters:

Server-Side Virtual Scrolling

For truly massive datasets, load data on demand as the user scrolls:

<ArcadiaDataGrid TItem="Transaction"
                 ItemsProvider="@LoadTransactions"
                 VirtualizeRows="true"
                 Height="600px"
                 TotalItemCount="@totalCount">
    <ArcadiaGridColumn Field="@nameof(Transaction.Id)" Header="ID" Width="100" />
    <ArcadiaGridColumn Field="@nameof(Transaction.Date)" Header="Date" Format="d" />
    <ArcadiaGridColumn Field="@nameof(Transaction.Amount)" Header="Amount" Format="C2" />
    <ArcadiaGridColumn Field="@nameof(Transaction.Status)" Header="Status" />
</ArcadiaDataGrid>

@code {
    private int totalCount = 500_000;

    private async ValueTask<ItemsProviderResult<Transaction>> LoadTransactions(
        ItemsProviderRequest request)
    {
        var results = await TransactionService.GetPageAsync(
            request.StartIndex, request.Count, request.CancellationToken);

        return new ItemsProviderResult<Transaction>(results, totalCount);
    }
}

The grid only fetches the rows currently in view, keeping memory usage flat.

Performance Benchmarks

Tested on a mid-range laptop (i5-1240P, 16 GB RAM, Chrome 126):

Row CountInitial RenderScroll FPSMemory (DOM)
1,00045 ms60 fps2.1 MB
10,00048 ms60 fps2.1 MB
100,00052 ms60 fps2.2 MB
500,00055 ms59 fps2.3 MB
1,000,00060 ms58 fps2.4 MB

Initial render time stays nearly constant because only ~30 rows are ever in the DOM.

How It Compares

ArcadiaBlazor VirtualizeMudBlazorRadzenSyncfusion
Max rows tested1M+100K50K100K500K
Fixed headersYesNoYesYesYes
Column pinningYesNoNoYesYes
Sort + virtualizeYesManualPartialYesYes
Filter + virtualizeYesManualPartialYesYes
Server-side pagingYesYesNoYesYes
Configurable overscanYesYesNoNoYes
Smooth scroll60 fps55-60 fps40-50 fps55 fps55 fps
Price$299/dev/yrBuilt-inFree (MIT)Free tier$995+/year

Tips for Best Performance

  1. Set ItemSize accurately — mismatched row heights cause scroll jank
  2. Use OverscanCount="10" — prevents blank flashes during fast scrolling
  3. Avoid complex templates — keep cell renderers lightweight
  4. Use server-side mode for 500K+ rows — don’t load everything into memory
  5. Pin key columns — pinned columns render in a separate viewport for smooth horizontal scroll

Try It

dotnet add package Arcadia.DataGrid

Virtual scrolling is included in the Arcadia DataGrid Pro package ($299/dev/year). View pricing.

Ready to try Arcadia?

Start with the free Community edition — 4 chart types, sparklines, notifications, and a full theme engine.