Handling High-Frequency Data in Chart.js with the Decimation Plugin
Learn how to use the Chart.js Decimation plugin to optimize the rendering of massive time-series datasets without losing critical visual outliers.
10 Feb 2026, 23:10 UTC

The Browser Lag Problem with Large Datasets
When visualizing time-series data—such as server telemetry or sensor logs—you often encounter datasets with tens of thousands of points. Attempting to render 50,000 points on a canvas that is only 800 pixels wide is inefficient; the browser spends CPU cycles drawing points that overlap the same pixel, leading to UI freezes, sluggish zooming, and potential browser crashes.
The solution is Data Decimation. Instead of forcing the rendering engine to process every single coordinate, decimation reduces the number of points drawn on the screen while attempting to preserve the visual shape and outliers of the original data.
How Decimation Works in Chart.js
The Decimation plugin acts as a pre-processor. It intercepts the data before it reaches the drawing loop, sampling the dataset based on a specific algorithm. For this to work, Chart.js requires a specific configuration: the chart must be a line type, and the x-axis must be a linear or time scale.
Choosing an Algorithm: Min-Max vs. LTTB
The plugin offers two primary strategies for reducing data:
- Min-Max: This algorithm divides the data into buckets and preserves only the minimum and maximum values within each bucket. This is critical for monitoring systems where a single spike (an outlier) is more important than the average trend.
- LTTB (Largest Triangle Three Buckets): This is a more sophisticated downsampling method that aims to maintain the visual characteristics and "perceived" shape of the original line, reducing the jaggedness often seen in simple sampling.
Implementation Requirements
Decimation is not a "plug-and-play" feature; it requires you to change how Chart.js handles data parsing. By default, Chart.js parses data to ensure it is in the correct format. However, for the decimation plugin to function, you must set parsing: false. This means you are responsible for providing data in a format the library can use directly (usually an array of objects with x and y values).
Configuration Example
Below is a configuration for a line chart handling a large dataset using the min-max algorithm. This should be implemented in your frontend JavaScript file where the Chart instance is initialized.
const config = {
type: 'line',
data: {
datasets: [{
label: 'Sensor Data',
data: largeDataset, // Array of {x: number, y: number}
showLine: true
}]
},
options: {
parsing: false, // Required for decimation
scales: {
x: {
type: 'linear', // Must be 'linear' or 'time'
}
},
plugins: {
decimation: {
enabled: true,
algorithm: 'min-max', // Preserves peaks and valleys
}
}
}
};
Risk Check: If you set the x-axis to category, the decimation plugin will be ignored, and the chart may fail to render or suffer from the same performance lag you are trying to avoid.
Trade-offs and Limitations
While decimation solves the rendering bottleneck, it introduces a few technical trade-offs:
- Memory vs. Rendering: Decimation reduces the number of draw calls to the canvas, but it does not reduce the memory footprint. The full dataset still resides in the browser's RAM. If your dataset is so large that it exceeds available memory, you must implement server-side aggregation instead.
- Aliasing: High-frequency oscillations can be smoothed out. If your data contains rapid, small fluctuations that aren't the absolute min/max of a bucket, they may disappear from the visual representation.
- Data Sorting: The plugin assumes data is already sorted by the x-axis. If your data arrives out of order, the decimation logic will produce an incorrect visual representation.
Verifying the Result
To verify that decimation is working, you can use the browser's Performance tab in DevTools. Compare the Scripting and Rendering time when enabled: true versus enabled: false. With a dataset of 10,000+ points, you should see a significant drop in the time spent in the draw() cycle. Additionally, check that the highest peaks in your raw data are still visible on the chart; if they are, the min-max algorithm is functioning correctly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.