---
title: "48 new BadgerQL functions, and `fill` now works on grouped charts"
date: "2026-09-14"
publisher: Honeybadger
url: "https://www.honeybadger.io/changelog/badgerql-improved-fill/"
---

When a count chart was grouped by status or host, a status with no events in a time window had no row for that window. This meant that the status line would run across the empty window to the next data point instead of dropping to zero.

The new `across` clause for `fill` adds the missing rows. We've also added **48 new BadgerQL functions**, including conditional aggregates that count, sum, or average only matching events without a second query.

### Fill every series, not just time

`fill` used to fill only one dimension, usually time. Now, with **`across`**, it fills every combination of values:

```
stats count() as ct by bin(10m) as t, status::int | fill t across status
```

Every (time, status) pair gets a row, and the missing counts become zero.

![In the before picture, the 404 and 500 lines run straight across hours with no rows.](https://www-files.honeybadger.io/changelog/badgerql-improved-fill/badgerql-fill-before-light.png)

_Before: the 404 and 500 lines run straight across hours with no rows._

![In the after picture,  each status drops to zero when nothing happened.](https://www-files.honeybadger.io/changelog/badgerql-improved-fill/badgerql-fill-after-light.png)

_After `fill t across status`: each status drops to zero when nothing happened._

A few more `fill` changes:

- **Step inference:**`fill t` is enough. The step comes from the `bin()` or `bucket()` in the same `stats` stage. Change `bin(5m)` to `bin(1h)` and the fill follows.
- **More `across` options:**`including` keeps a fixed set of values in your legend, `bounded` limits each series to the time it was active, and `across` works without a time dimension too.

### Conditional aggregates

The new **`*If` aggregates** take a condition, so you can get error counts and totals from one query:

```
stats count() as total, countIf(status::int >= 500) as errors by bin(5m)
```

The family is `countIf`, `sumIf`, `avgIf`, `minIf`, `maxIf`, `uniqueIf`, `firstIf`, `lastIf`, `percentileIf`, and `apdexIf`.

### Rates and histograms

**`rate()`** turns an aggregate into a per-second rate:

```
stats rate(count()) as rps by bin()
```

Use a bare `bin()` and the rate stays per second as you zoom. Pass an interval as the second argument for a different unit: `rate(count(), 1m)` is per minute.

**`bucket()`** does for numbers what `bin()` does for time. This latency histogram groups durations into 100 ms buckets, and `fill b` adds the empty buckets:

```
stats count() by bucket(duration::int, 100) as b | fill b
```

Use `bucket(value, min, max, n)` for a fixed number of buckets instead.

### And the rest

The other new functions cover math, dates, URLs, IP ranges (`inCIDR`), JSON validation, strings (`split`, `position`, `editDistance`, `similarity`), hashing, and arrays. New aggregates include `median`, `stddev`, `corr`, `pickMin`, and `pickMax`. See [Expression functions](https://docs.honeybadger.io/guides/insights/badgerql/#expression-functions) for the full list.

All of this works today in the Insights query editor and dashboard widgets, with no setup. Insights is included on every Honeybadger plan, including the free Developer plan. Check out the [BadgerQL guide](https://docs.honeybadger.io/guides/insights/badgerql/) to learn more.

---

## Try Honeybadger for FREE

Intelligent logging, error tracking, and Just Enough APM™ in one dev-friendly platform. Find and fix problems before users notice.

[Start free trial](https://app.honeybadger.io/users/sign_up)

[See plans and pricing](https://www.honeybadger.io/plans/)
