Repository navigation
Description
What happened?
A time chart with a positive Series Limit picks its top N groups from the newest query chunk only. By default that chunk is the last 15 minutes of the range. A group that was busy earlier but quiet at the end drops off the chart, even if it was the biggest series in the range. On a 24h or 7d chart this can hide exactly the spike you are looking for.
The docs say something different:
- The Series Limit field in Display Settings says it keeps "those with the largest values".
- The MCP/API schema says it "keeps the top-N groups by aggregated value over the queried range".
Nothing tells the user that "largest" only covers the last few minutes.
What should happen: the top N groups are ranked over the whole chart range, as the docs describe. At minimum, the UI and API docs should say how the ranking works.
Steps to reproduce
- Use the default
otel_logsschema. Insert logs forServiceName = 'svc-a', 10,000 rows spread over 23 hours starting 24 hours ago, and none in the last hour. Insert logs forServiceName = 'svc-b', 10 rows in the last 5 minutes. - Create a dashboard tile: a line chart,
count()grouped byServiceName, granularity auto, time range "Last 24 hours". - In Display Settings, set Series Limit to
1. - The chart shows only
svc-b.svc-ais gone, although it has 1,000 times more events in the range. - Turn off query chunking for the tile, or set Series Limit to
0.svc-acomes back.
How are you running HyperDX?
ClickStack Cloud, where we saw the symptom on 24h dashboard tiles. The root cause below is traced in the code on main @ 6767349. The behaviour came in with #2449 and is still on main.
Where does it show up?
Dashboard and chart-explorer time charts (builder line and stacked bar charts with a group-by), and tiles created through the external API or MCP with seriesLimit.
Root cause
- Time charts are fetched in chunks, and chunking is on by default for dashboard time charts: DBTimeChart.tsx#L501.
- Chunks are built newest-first, and the first one is 15 minutes: searchWindows.ts#L2-L8, useChartConfig.tsx#L125-L168.
- The ranking range for every chunk is pinned to that newest chunk:
rankingDateRange = windows[0]?.dateRangeat useChartConfig.tsx#L194-L213. The code comment there names the trade-off: "groups with no events in the newest window are dropped from the chart." - The
__hdx_series_limitCTE then ranks groups only over that range: renderChartConfig.ts#L1535-L1553. - The docs promise ranking over the full range: schemas.ts#L104-L109, ChartDisplaySettingsDrawer.tsx#L293-L294.
#2449 chose the newest window to keep the ranking scan small, so that every chunk returns the same top-N set. The goal of one shared set across chunks is right. The range it uses is the problem.
Suggested fix direction
- Rank over the full chart range (
config.dateRange) and keep one shared set across chunks. To avoid scanning the full range once per chunk, run the ranking once before the chunks, then pass the resulting group list to each chunk as anIN (...)filter instead of repeating the CTE. - If a full-range scan is too expensive by default, make the ranking range explicit, for example "rank over: full range / most recent window". Then document the choice in the Display Settings copy and the API/MCP schema.
- Either way, update the Series Limit description in the UI and API docs so it matches the real behaviour.
Activity
brandon-pereira commentedon Sep 24, 2026
Hey @tefimov - thanks for raising this.
I see we even have a comment in the code highlighting this could be improved, so we agree! https://github.com/hyperdxio/hyperdx/blob/main/packages/app/src/hooks/useChartConfig.tsx#L197
I agree with the approaches listed above. We just need to ensure we balance query and render performance with accuracy. For that reason, my vote would be that we go with option B
I will track this internally as well and get it prioritized - but if you need it sooner please feel free to open a PR!