Splunk Summary Indexing: Pre-Aggregating Recurring Reports Without Re-Scanning Raw Data
Summary indexing pre-aggregates recurring Splunk reports into a dedicated index so dashboards stop re-scanning raw data. A worked sistats configuration, plus the time-alignment, backfill, and late-data pitfalls.
16 Jul 2025, 08:56 UTC

If a dashboard panel scans 30 days of raw events every time someone opens it, you are paying the search cost repeatedly for a question whose answer changes only once a day. Summary indexing fixes this: a scheduled search runs once, pre-aggregates the data, and writes the small result set into a dedicated summary index. Dashboards then query that index and return in seconds instead of minutes.
The trade-off is real, though. You lose ad-hoc flexibility, you must get the time alignment exactly right, and late-arriving data is silently missed. This guide walks through a working configuration, explains the mechanism, and covers the mistakes that cause double-counted or incomplete reports.
How the mechanism works
A summary-indexed saved search is a normal scheduled search with one difference: instead of returning results to a user, Splunk writes them as new events into a separate index (conventionally named summary). Each result row becomes one event, carrying the fields your search emitted plus metadata such as the source search name.
Because the data is already indexed, summary indexing does not consume additional license volume. It does consume indexer disk and I/O, and each populating search consumes scheduler capacity — both matter at scale.
A worked configuration: daily error counts by URI
Goal: a dashboard showing daily counts of HTTP 4xx/5xx responses per URI path, over the last 90 days, from an access log in index=main.
1. Create the summary index
On every indexer (or via the indexer cluster manager node's bundle), define the index in indexes.conf:
[summary]
homePath = $SPLUNK_DB/summary/db
coldPath = $SPLUNK_DB/summary/colddb
thawedPath = $SPLUNK_DB/summary/thawed
frozenTimePeriodInSecs = 7776000frozenTimePeriodInSecs = 7776000 keeps 90 days. Retention here is independent of the source index — a common pattern is short retention on the summary index while raw data is kept longer for compliance. In a search head cluster, every member must resolve the same index name, and the index must exist on all indexers, because any cluster member may end up executing the scheduled search.
2. Create the populating saved search
In Settings → Searches, reports, and alerts, create a search named Daily Error Count:
index=main sourcetype=access_combined status>=400
| sistats count by uri_path, statusSet the time range to earliest=-1d@d latest=@d (yesterday, midnight to midnight). Schedule it to run daily at 01:00. Under the summary indexing option, enable it and set the summary index to summary. Ensure addtime=true behavior so the summary events keep their original _time rather than the time the search ran — otherwise your timecharts will bunch everything at 01:00.
The sistats command is the key detail. It stores sufficient statistics (count, and if requested, sums, minimums, maximums, distinct-value digests) in reserved fields with a psrsvd_ prefix. That is what lets a later report run a plain stats over the summary data and get correct answers without touching raw events.
3. Query the summary index
index=summary source="Daily Error Count"
| stats count by uri_path, statusNote this uses stats, not sistats — the si* commands are for writing; the reporting search reads with normal transforming commands and Splunk reconciles the sufficient statistics automatically.
Preview before you write
Before enabling the schedule, dry-run the populating search from the search bar (as a user with the appropriate capabilities, typically admin or a role with schedule_search):
index=main sourcetype=access_combined status>=400 earliest=-1d@d latest=@d
| sistats count by uri_path, status
| collect index=summary addtime=true testmode=truetestmode=true shows what would be written without writing it. Check that rows, fields, and counts look right. After the first scheduled run, verify with index=summary source="Daily Error Count" and confirm the psrsvd_* fields are present. Then compare dashboard performance in the Job Inspector: scanCount and eventCount should drop by orders of magnitude versus the raw search.
Limits and the mistakes that bite
Plain stats destroys re-aggregation ability
If the populating search uses stats count by uri_path instead of sistats, the summary stores only final counts. You can never later compute an average, a percentile, or regroup by a different field — the intermediate information is gone. Use sistats, sichart, or sitimechart whenever the downstream aggregation might change.
Time misalignment causes double-counting and gaps
The populating search's time window must tile cleanly with its schedule. A daily search over -1d@d to @d run once a day covers each day exactly once. If you instead run it every 12 hours over a 24-hour window, every event gets counted twice. If the scheduler skips a run (check index=_internal sourcetype=scheduler status=skipped), that day is simply missing until you backfill.
Late-arriving data is silently missed
Summary indexing keys off event time at the moment the search runs. Events for yesterday that get indexed after 01:00 are never picked up. If your sources lag, add a lookback: for example, run daily over earliest=-2d@d latest=-1d@d so each day is captured after a 24-hour grace period — but then make sure each day is written exactly once, or deduplicate downstream.
Only emitted fields survive
The summary index contains exactly the fields the populating search output. If you later want to drill into user agents or client IPs and you didn't group by them, that data does not exist in the summary. Storing _raw preserves drill-down but largely defeats the size savings.
Backfill is a separate step
Enabling the schedule only runs the search forward. To populate history, run a one-off backfill:
| savedsearch "Daily Error Count" earliest=-30d@d latest=@d
| collect index=summary addtime=trueBe careful: if the saved search internally snaps to its own time modifiers, you may need to clone it with an explicit window for backfill purposes, and slice the backfill into day-sized chunks so windows don't overlap. Validate per-day counts against a raw-data spot check afterward. Splunk also ships a fill_summary_index.py script for backfilling via the scheduler's own machinery.
Scheduler load
Hundreds of summary searches can saturate the scheduler and cause skipped runs across the whole deployment. Consolidate populating searches where one search can emit multiple groupings, stagger schedules away from the top of the hour, and monitor skipped-search counts as a health metric.
Verifying the payoff
Three concrete checks: (1) index=summary source="Daily Error Count" returns the expected rows per day with no duplicate days; (2) the Job Inspector on the summary-backed dashboard shows a small scanCount relative to the raw version; (3) Settings → Licensing shows no increase in indexed volume attributable to the summary index. If counts ever look wrong, suspect time alignment or a backfill overlap before suspecting the aggregation itself.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.