---
title: "Large Dataset Interactivity"
framework: javascript
version: "14.1.0"
---

# Large Dataset Interactivity

AG Charts is optimised to handle **large datasets with over 1 million points**, while maintaining full, smooth interactivity. No additional configuration or modules required - it just works out of the box.

#### Ordered Data

```ts
import {
  AgCartesianAxisOptions,
  AgCartesianChartOptions,
  AgCartesianSeriesOptions,
  AgCharts,
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  BubbleSeriesModule,
  CandlestickSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  CrosshairModule,
  HistogramSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NavigatorModule,
  NumberAxisModule,
  OhlcSeriesModule,
  OrdinalTimeAxisModule,
  RangeAreaSeriesModule,
  RangeBarSeriesModule,
  ScatterSeriesModule,
  TimeAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import { getData } from "./data";

let dataLabel = "1K";
let seriesType = "Line";
let datapoints = 1e3;
const timeAxes: Record<string, AgCartesianAxisOptions> = {
  x: { type: "ordinal-time", parentLevel: { enabled: true } },
};
const numberAxes: Record<string, AgCartesianAxisOptions> = {
  x: { type: "number" },
};
const baseData = getData(1e6);
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  BubbleSeriesModule,
  CandlestickSeriesModule,
  CrosshairModule,
  HistogramSeriesModule,
  LegendModule,
  LineSeriesModule,
  NavigatorModule,
  NumberAxisModule,
  OhlcSeriesModule,
  OrdinalTimeAxisModule,
  RangeAreaSeriesModule,
  RangeBarSeriesModule,
  ScatterSeriesModule,
  TimeAxisModule,
  ZoomModule,
  CategoryAxisModule,
  ContextMenuModule,
]);

const options: AgCartesianChartOptions = {
  data: baseData.slice(-datapoints),
  title: { text: `${seriesType} with ${dataLabel} datapoints` },
  animation: { enabled: false },
  zoom: {
    enabled: true,
    axes: "x",
    anchorPointX: "pointer",
    anchorPointY: "pointer",
    autoScaling: {
      enabled: true,
    },
  },
  navigator: {
    enabled: true,
    miniChart: {
      enabled: true,
    },
  },
  series: [
    {
      type: "line",
      xKey: "timestamp",
      yKey: "close",
    },
  ],
  axes: timeAxes,
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);

function setSeries(type: string, label: string) {
  seriesType = label;
  let series: AgCartesianSeriesOptions[] = [];
  switch (type) {
    case "bar":
    case "area":
    case "line":
      options.series = [
        {
          type,
          xKey: "timestamp",
          yKey: "high",
        },
      ];
      break;
    case "stacked-bar":
    case "stacked-area":
      const stackedType = type === "stacked-bar" ? "bar" : "area";
      options.series = [
        { type: stackedType, xKey: "timestamp", yKey: "open", stacked: true },
        { type: stackedType, xKey: "timestamp", yKey: "close", stacked: true },
      ];
      break;
    case "range-area":
    case "range-bar":
      options.series = [
        {
          type,
          xKey: "timestamp",
          yLowKey: "low",
          yHighKey: "high",
        },
      ];
      break;
    case "candlestick":
    case "ohlc":
      options.series = [
        {
          type,
          xKey: "timestamp",
          lowKey: "low",
          highKey: "high",
          openKey: "open",
          closeKey: "close",
        },
      ];
      break;
    case "scatter":
      options.series = [
        {
          type,
          xKey: "x",
          yKey: "y",
          fillOpacity: 0.2,
          strokeOpacity: 0.2,
        },
      ];
      break;
    case "bubble":
      options.series = [
        {
          type,
          xKey: "x",
          yKey: "y",
          sizeKey: "size",
          fillOpacity: 0.2,
          strokeOpacity: 0.2,
        },
      ];
      break;
    case "histogram":
      options.series = [
        {
          type,
          xKey: "close",
        },
      ];
      break;
    default:
      return;
  }
  const newDatapoints = (options.series?.[0] as any)?.stacked
    ? datapoints / 2
    : datapoints;
  if (options.data?.length !== newDatapoints) {
    options.data = baseData.slice(-newDatapoints);
  }
  if (type == "bubble" || type == "scatter" || type == "histogram") {
    options.zoom!.axes = "xy";
    options.zoom!.autoScaling!.enabled = false;
    options.navigator!.enabled = false;
    options.axes = numberAxes;
  } else {
    options.zoom!.axes = "xy";
    options.zoom!.autoScaling!.enabled = true;
    options.navigator!.enabled = true;
    options.axes = timeAxes;
  }
  options.title!.text = `${seriesType} with ${dataLabel} datapoints`;

  chart.update(options);
}

function setData(points: number, label: string) {
  const newDatapoints = (options.series?.[0] as any)?.stacked
    ? points / 2
    : points;
  if (options.data?.length !== newDatapoints) {
    options.data = baseData.slice(-newDatapoints);
  }
  dataLabel = label;
  datapoints = points;
  options.title!.text = `${seriesType} with ${dataLabel} datapoints`;

  chart.update(options);
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).setSeries = setSeries;
  (<any>window).setData = setData;
}
```

[Live example: Ordered Data](https://www.ag-grid.com/charts/typescript/large-dataset-interactivity/examples/ordered-data)

In the above example:

- Use the controls to select different series types and data sizes.
- Use the mouse, [Navigator](https://www.ag-grid.com/charts/javascript/navigator/) or [zoom controls](https://www.ag-grid.com/charts/javascript/zoom/#axis-zoom-controls) to [zoom](https://www.ag-grid.com/charts/javascript/zoom/), [scroll](https://www.ag-grid.com/charts/javascript/zoom/#scrolling) and [pan](https://www.ag-grid.com/charts/javascript/zoom/#panning) the data.

> **Note**
>
> Performance may vary based on your specific use case, environment and hardware.

## How it works

Behind the scenes, AG Charts applies advanced data aggregation techniques, such as the [M4 algorithm](https://blog.ag-grid.com/optimizing-large-data-set-visualisations-with-the-m4-algorithm/), to ensure accurate representation across scales. As you zoom and pan, the chart dynamically adapts to the visible range, preserving both performance and clarity.
