Sampling Strategies in Cribl Stream That Won't Blind Your Detections

Rate limits, dynamic sampling, and route-level sampling: how to cut volume without losing the events investigations need.

What sampling does (and what it silently does) to your data

Per Cribl's reference, the Sampling Function "filters out events, based on an expression and a sampling rate." You don't pick which events survive; you pick a rate and let the Function choose. Each sampling rule pairs a filter expression with a Sampling Rate, and "Sampling will pick 1/N events matching this rule," where N is an integer that defaults to 1. The page's own illustration: "Setting this Function's Sampling rate to 30 would mean that only 1 of every 30 events would be kept."

The page verifies the mechanism with a small capture: 100 events from a datagen Source run through a rate of 30, and the capture file's Basic Statistics view showed "about 4 of the original 100 events, or close to 1 in 30" surviving. The ratio works out asymptotically, which is exactly what "1 of every 30" promises.

Two quieter behaviors are worth knowing before you turn a rate dial. First, sampling applies per rule, so events no rule claims aren't sampled: in Cribl's ingest-time sampling use case, only the 200 events match the rule, and it notes you get "(and all other events at 1:1)." The design leans on that deliberately: "still bring in all potentially erroneous events (400s, 500s, etc.) that can be used for troubleshooting." Second, every event that passes a Sampling Function acquires "an index-time sampled::<rate> field," which "You can use in your statistical functions, as necessary." Sampled data still carries its rate with it, so consumers can weight for what was dropped.

The reference page also carries the shared-nothing caveat: "Each Worker Process executes this Function independently on its share of events." Each worker applies the rate to its own share of traffic.

The Sampling function, configured

The documented configuration surface is small. A Sampling Function takes a Filter, "Filter expression (JavaScript) that selects data to feed through the Function. Defaults to true, meaning it evaluates all events", a Description, a Final toggle used "to stop feeding data to the downstream Functions," and the Sampling rules, each with its own Filter expression and integer Sampling Rate.

The ingest-time sampling use case shows the complete assembly on a real stream. A Regex Extract Function first pulls the HTTP status out of _raw into a field called __status, and the page notes that "fields that start with __ are special fields in Cribl Stream, and can be used anywhere in a Pipeline." Then the Sampling Function is "scoped to all events where sourcetype=='access_combined'," with a rule condition of __status == 200 and a Sample Rate of 5. Assembled from the fields the page documents:

Filter:                 sourcetype=='access_combined'
Sampling rules
  Filter:               __status == 200
  Sampling Rate:        5

Read that block the way the use case describes it: the verbose successes are reduced to one in five, while everything the rule filter doesn't claim (the 400s, the 500s, the rest) continues at full volume.

Dynamic sampling for voluminous traffic

The Dynamic Sampling Function "filters out events based on an expression, a sample mode, and the volume of events." The difference from the Sampling Function is who sets the rate. "Compared to static sampling, where users must first select a sample rate, Dynamic Sampling allows for automatically adjusting sampling rates, based on the volume of incoming events per sample group." You configure the aggressiveness of the adjustment; event volume does the rest.

The cadence is the Sample period, an advanced setting that defaults to 30 seconds. A brand-new group starts at a rate of 1:1 for one period; "Once Sample Period seconds have elapsed, a sample rate will be derived based on the configured Sample Mode, using the sample group's event volume during the previous sample period." Two more advanced settings guard the edges: Minimum events (default 30): a group below that volume in the previous period gets "a sample rate of 1:1", and Sampling rate limit, above which "the rate will be limited to this value."

Here is the page's own example configuration, with its reported outcome:

Sample Mode:         Square Root
Sample Period (sec): 20
Minimum Events:      3
Max. Sampling Rate:  3

With those settings, the example reduced Events In from 4.23K to Events Out of 1.41K. The page is explicit that "Your own results will vary depending on multiple parameters - the Sample Group Key, Sample Period, Minimum Events, Max Sampling Rate, and rate of incoming events."

One warning deserves its own paragraph, because it inverts a common intuition. The docs do not recommend dynamic sampling for high-cardinality traffic; they warn against it. The Function "stores the state of each unique sample group key in memory on every Worker Node Process," has "no cache size limit," and "sample groups are not removed when they go idle", memory "grows with the number of unique keys your events produce." The page's own advice: "Choose low-cardinality fields such as host or domain," because "High-cardinality fields such as message text or session IDs can cause unbounded memory growth and out-of-memory errors on Worker Nodes." The correct reading of this Function is voluminous traffic with low-cardinality grouping, not the reverse.

Route-level control

The use case sets the scene plainly: you want to analyze and troubleshoot "highly verbose/voluminous data - for example, CDN logs, ELB Access Logs, or VPC Flows," but you "were concerned about storage requirements and search performance." Sampling is the mechanism the docs reach for there. Structurally, its first step is to "make sure you have a Route and Pipeline configured to match desired events" before any Function is added. Functions run in Pipelines, Pipelines attach to Routes, so the Sampling Function in that example only ever sees the events its route matched (scoped to sourcetype=='access_combined'), and its rule then narrows the sampling to the subset its filter claims.

That layering is what makes route-level control practical in a detection-first environment. The verbose streams (access logs, CDN, VPC flow data) get pipelines where a sampling rule does the cutting, while the streams investigations depend on can run through routes that contain no sampling Function at all. The volume decision is then made once per route, in that route's Pipeline, rather than applied globally or guessed per event.

What never gets sampled

Nothing is exempted by a flag; sampling is filtering, and what the filters don't claim flows through. The use case names the design directly: the point is "to lower the volume of all verbose successes (200s), but still bring in all potentially erroneous events (400s, 500s, etc.) that can be used for troubleshooting." The 400s and 500s survive because the rule filter is __status == 200. They pass at 1:1 not by any protection, but by non-matching.

The three pages verified here do not extend that rule to security, auth, or detection data, so the following is our own rule of thumb as a Cribl partner, not doc text: scope sampling rules so that streams feeding detections (auth, firewall, access, and anything an investigation depends on) travel through routes with no Sampling Function, and reserve sampling for the verbose traffic. And wherever you do sample, static or dynamic, keep the sampled::<rate> field visible to your consumers so their statistics stay weighted correctly.

Frequently asked questions

How does the Cribl Stream Sampling Function decide which events survive?

You set a rate, and the Function keeps one of every N events that match its rule. Events no rule claims are not sampled and pass through unchanged at full volume.

How does Cribl Stream Dynamic Sampling differ from static sampling?

Dynamic Sampling adjusts the rate automatically from the event volume per sample group, instead of taking a fixed rate. Sample modes such as Logarithmic and Square Root set how aggressive the adjustment is.

Why do the docs warn against Cribl Stream dynamic sampling for high-cardinality groups?

The Function keeps every unique sample group key in memory, and groups are not removed when they go idle. High-cardinality keys like message text or session IDs can cause unbounded memory growth and out-of-memory errors.

How do Cribl Stream routes keep detection data out of sampling?

A Sampling Function only sees the events its route matched, since Functions run in Pipelines and Pipelines attach to Routes. Detection streams can travel through routes that contain no sampling Function.

Verified against Cribl Stream 4.20 documentation on September 30, 2026.

Ready to Reduce Your SIEM Costs?

Get a personalized demo and see how Cribl can save you 50-80% on data costs.

Schedule Free Demo