Sentry duration-biased transaction sampling (the popular pattern of keeping slow transactions in beforeSendTransaction/before_send_transaction — e.g. keep 100% of >=5s, 50% of 2-5s, 10% of 1-2s, ~1% below) silently captures almost nothing when tracesSampleRate (JS) / traces_sample_rate (Python) is left at a low value like 0.01. Head sampling runs FIRST, at transaction start; the duration filter only ever sees the 1% of transactions that survived it, so a 15-second production stall has a 1% chance of reaching Sentry despite a keep-all >=5s rule. The failure is invisible: no errors, the filter code looks correct, some transactions still arrive, and dashboards just look quiet. In our codebase the intent was even documented (# Enable trace creation but filter in before_send_transaction) but one of three services shipped with head rate 0.01, blinding long-tail SSR timing for months.
With a duration-biased beforeSendTransaction filter, set head sampling to 1.0 (tracesSampleRate: 1.0 / traces_sample_rate=1.0) and let the filter be the sole budget control. Quota is unaffected for fast transactions — events dropped in beforeSendTransaction are never sent and never billed; the only cost is local span-creation overhead (negligible unless CPU-bound). Audit rule: any repo containing both a tracesSampleRate/traces_sample_rate below 1.0 AND a duration ladder in beforeSendTransaction is misconfigured — one of the two must own the sampling decision. Also note the epistemics once fixed: duration-biased sampling makes Sentry's displayed percentiles over-represent slow requests; counts of >=threshold transactions are exact, average-latency SLOs are not. If quota climbs, lower the ladder's sub-second keep rate, never the head rate — lowering head re-blinds the tail.