Optimizing Large Datasets in Chart.js with the Decimation Plugin
Learn how to use the Chart.js Decimation plugin to maintain high performance when rendering thousands of data points in line charts using LTTB and min-max algorithms.
11 Jul 2025, 05:27 UTC

The Performance Bottleneck of High-Density Charts
When rendering line charts with thousands of data points, Chart.js can suffer from significant frame rate drops during zooms, pans, and initial renders. This happens because the browser attempts to draw every single point on the HTML5 Canvas, even if multiple points occupy the same horizontal pixel.
The Decimation plugin solves this by reducing the number of points passed to the rendering engine. Instead of drawing 10,000 points, the plugin samples the data down to a manageable number based on the available pixel width, significantly reducing CPU and GPU overhead without losing the overall visual trend of the data.
Implementation Requirements
Decimation is not a "plug-and-play" feature for every chart. For the plugin to activate, your configuration must meet these three strict criteria:
- Chart Type: Must be a
linechart. - X-Axis Scale: Must be set to
linear. It will not function withcategoryortimescales. - Data Sorting: Data must be sorted by the x-axis value in ascending order.
Worked Configuration: LTTB vs. Min-Max
Chart.js provides two primary algorithms for decimation. min-max is computationally cheaper but can look blocky. lttb (Largest Triangle Three Buckets) is the industry standard for downsampling because it preserves visual peaks and troughs, ensuring that outliers remain visible.
// Run this in your frontend JavaScript file
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Sensor Data',
data: largeDataSet, // Array of {x: number, y: number}
parsing: false, // Optimization: disable parsing for large sets
normalized: true, // Optimization: tell Chart.js data is already sorted
}]
},
options: {
scales: {
x: {
type: 'linear', // Required for decimation
}
},
plugins: {
decimation: {
enabled: true, // Activates the plugin
algorithm: 'lttb', // 'lttb' preserves visual peaks better than 'min-max'
samples: 500, // Target number of points to render
}
}
}
});
Key Configuration Details
| Property | Requirement/Risk | Expected Result |
|---|---|---|
parsing: false |
Requires data in {x, y} format |
Bypasses internal data transformation for speed |
normalized: true |
Data must be sorted by X | Skips internal sorting checks |
algorithm: 'lttb' |
Higher CPU cost than min-max | Accurate visual representation of spikes |
Limitations and Common Pitfalls
The most common reason the decimation plugin fails to work is the use of a category scale (the default for many line charts). If your x-axis labels are strings (e.g., "Jan", "Feb"), the plugin will be ignored. You must convert these to numerical values or use a linear scale to enable sampling.
Another limitation is the sampling threshold. If the number of data points is lower than the samples value defined in the config, the plugin does nothing. It only triggers when the dataset exceeds the specified sample limit.
Verifying the Result
To verify that decimation is functioning, you can use the browser's Performance tab in Developer Tools:
- Load the chart with 10,000+ points and
decimation: { enabled: false }. Note the "Scripting" time during the initial render and the frame rate during a zoom interaction. - Enable decimation and set the
algorithmtolttb. - Observe the reduction in CPU usage. Visually, the line should look identical to the full dataset, but the interaction (hovering/zooming) should feel fluid.
If the chart disappears or renders a single straight line, double-check that your data is sorted by the x-axis; unsorted data will cause the LTTB algorithm to produce erratic visual artifacts.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.