<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju" -->

---
title: How to build a sales dashboard on a million real rows in...
description: A walkthrough of building a sales dashboard that loads over a million real transaction rows entirely into the browser, using a React DataGrid and PivotGrid...
canonical: https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: How to build a sales dashboard on a million real rows in React DataGrid | daily.dev
og:description: A walkthrough of building a sales dashboard that loads over a million real transaction rows entirely into the browser, using a React DataGrid and PivotGrid...
og:url: https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju
og:image: https://api.daily.dev/og/posts/oMh9SxwJu.png
og:image:alt: How to build a sales dashboard on a million real rows in React DataGrid
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How to build a sales dashboard on a million real rows in React DataGrid

**[DEV](https://daily.dev/sources/devto)** · 8 min read · 1 upvotes · 0 comments

## Summary

A walkthrough of building a sales dashboard that loads over a million real transaction rows entirely into the browser, using a React DataGrid and PivotGrid from KanuniLabs, rather than paginating through server queries. Covers compressing the dataset into dictionary-encoded columns (5.8 MB gzipped), decoding it in chunks, sorting via a Web Worker, full-text search across formatted columns, grouping, and a country-by-year revenue pivot with charting. Highlights a performance gotcha where an unmemoized Intl.NumberFormat call inside toLocaleString turned a 6-second search index build into over a minute, and closes with a candid list of trade-offs: download size, memory footprint, first-time indexing costs, and when a server-side approach is still the better fit.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://dev.to/kanunilabs/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-4io8>

## Questions this post answers

### Why does using toLocaleString with currency options inside a value formatter slow down a large data grid so much?

Calling toLocaleString with formatting options constructs a brand-new Intl.NumberFormat instance on every invocation. In a grid formatting a million rows during the first search index build, this pushed processing time to over a minute in a development build, compared to about six seconds when a single shared Intl.NumberFormat instance was reused for every row.

_Anyone tuning a large React data grid can compare formatter tricks like this one on daily.dev._

### How much can compressing a large CSV dataset into dictionary-encoded columns reduce its download size for a browser app?

A 91 MB CSV of over a million retail transaction rows was reduced to 5.8 MB gzipped by encoding repeated columns (invoice, description, country, and similar) as small dictionaries plus one integer per row, instead of shipping the full gzipped CSV at 14.8 MB. This made loading the entire dataset into a browser tab practical for a client-side dashboard.

_Developers weighing client-side versus server-side data loading can find approaches like this on daily.dev._

### Is it feasible to load a million rows of data directly into the browser and do all sorting, filtering, and pivoting client-side instead of querying a server?

Yes, for a dataset around a million rows and roughly 5.8 MB compressed, loading it entirely into the browser and handling sorting, searching, grouping, and pivoting client-side is workable, with sorting offloaded to a Web Worker to keep the page responsive. Trade-offs include a one-time 5.8 MB download, around 350 MB of memory once everything is touched, and first-time search indexing costs of several seconds; it is not suited to private, rapidly changing, or much larger datasets.

_Teams deciding between client-side and server-side dashboard architectures can track real-world trade-offs like these on daily.dev._

## Similar posts on daily.dev

- [Building Interactive Analytics Dashboards with React Pivot Table and D3.js](https://daily.dev/posts/building-interactive-analytics-dashboards-with-react-pivot-table-and-d3-js-ofsshlkcq) · Syncfusion · 0 upvotes · 0 comments
- [Build Fast, Scalable React Data Grids for Large Datasets Using Virtualization \[Webinar Show Notes\]](https://daily.dev/posts/build-fast-scalable-react-data-grids-for-large-datasets-using-virtualization-webinar-show-notes--grkoxcqia) · Syncfusion · 1 upvotes · 0 comments
- [How to Build an Interactive University Ranking System Using React and Data Viz Tools](https://daily.dev/posts/how-to-build-an-interactive-university-ranking-system-using-react-and-data-viz-tools-11yrxeuny) · freeCodeCamp · 3 upvotes · 0 comments
- [Building a Modern Digital Product Dashboard UI with React.js](https://daily.dev/posts/building-a-modern-digital-product-dashboard-ui-with-react-js-1z9nzj55n) · Medium · 3 upvotes · 0 comments

---

Tags: [#webdev](https://daily.dev/tags/webdev), [#javascript](https://daily.dev/tags/javascript), [#react](https://daily.dev/tags/react), [#performance](https://daily.dev/tags/performance)

[View this post on daily.dev](https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"How to build a sales dashboard on a million real rows in React DataGrid","url":"https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju"},"datePublished":"2026-09-29T10:37:39.420Z","dateModified":"2026-09-29T10:38:06.026Z","description":"A walkthrough of building a sales dashboard that loads over a million real transaction rows entirely into the browser, using a React DataGrid and PivotGrid...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/3267bbcb3567ce86dde0ec69eb2a9abc?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/3267bbcb3567ce86dde0ec69eb2a9abc?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"DEV","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"DEV","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/devto","url":"https://daily.dev/sources/devto"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"webdev,javascript,react,performance","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"DEV","item":"https://daily.dev/sources/devto"},{"@type":"ListItem","position":3,"name":"How to build a sales dashboard on a million real rows in React DataGrid"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/how-to-build-a-sales-dashboard-on-a-million-real-rows-in-react-datagrid-omh9sxwju#faq","mainEntity":[{"@type":"Question","name":"Why does using toLocaleString with currency options inside a value formatter slow down a large data grid so much?","acceptedAnswer":{"@type":"Answer","text":"Calling toLocaleString with formatting options constructs a brand-new Intl.NumberFormat instance on every invocation. In a grid formatting a million rows during the first search index build, this pushed processing time to over a minute in a development build, compared to about six seconds when a single shared Intl.NumberFormat instance was reused for every row. Anyone tuning a large React data grid can compare formatter tricks like this one on daily.dev."}},{"@type":"Question","name":"How much can compressing a large CSV dataset into dictionary-encoded columns reduce its download size for a browser app?","acceptedAnswer":{"@type":"Answer","text":"A 91 MB CSV of over a million retail transaction rows was reduced to 5.8 MB gzipped by encoding repeated columns (invoice, description, country, and similar) as small dictionaries plus one integer per row, instead of shipping the full gzipped CSV at 14.8 MB. This made loading the entire dataset into a browser tab practical for a client-side dashboard. Developers weighing client-side versus server-side data loading can find approaches like this on daily.dev."}},{"@type":"Question","name":"Is it feasible to load a million rows of data directly into the browser and do all sorting, filtering, and pivoting client-side instead of querying a server?","acceptedAnswer":{"@type":"Answer","text":"Yes, for a dataset around a million rows and roughly 5.8 MB compressed, loading it entirely into the browser and handling sorting, searching, grouping, and pivoting client-side is workable, with sorting offloaded to a Web Worker to keep the page responsive. Trade-offs include a one-time 5.8 MB download, around 350 MB of memory once everything is touched, and first-time search indexing costs of several seconds; it is not suited to private, rapidly changing, or much larger datasets. Teams deciding between client-side and server-side dashboard architectures can track real-world trade-offs like these on daily.dev."}}]}
```

