align [options(...)]?, [period: duration]?, [frame(...)]?, [metricAligningExpression: expression]+

Turns a raw metric-interface dataset into interval rows on a time grid by evaluating aggregate expressions that each pick exactly one series via m, m_tdigest, or m_object.

Shape and columns

The input must have metric-interface shape (wide tags plus metric name/value columns) and a valid-from timestamp. The output is an interval dataset: new valid_from and valid_to, all tag columns as the primary key, a hidden _c_bucket column holding the bin index, and one output column per binding.

Expressions and grouping

Every binding must contain at least one aggregate function, and each aggregate subtree must include exactly one metric selector—multiple metrics in one aggregate are rejected. group_by is not supported; grouping is always the full tag set. When present, an options argument must be the first argument.

Resolution, frames, and bins

You cannot combine options(bins: …) with an explicit period duration argument. A frame (back:…, ahead:…) or frame_exact chooses the aggregation window per grid step; otherwise a tumbling window between grid lines is used. Non-exact frames may be nudged so lengths divide the bin width.

Related verbs

aggregate and timechart are the main companions for metric rollups and charts.

Options

OptionTypeMeaning
binsint64Target maximum number of bins across the query window; bin width is chosen for a readable grid (not accelerable).
min_bindurationMinimum bin width; if the computed width would be smaller, this duration is used instead (not accelerable).
empty_binsboolWhen true, emit every bin in the window; missing data yields null in metric columns (not accelerable).

Categories

Accelerable

align is sometimes accelerable, depending on options used. A dataset that only uses accelerable verbs can be accelerated, making queries on the dataset respond faster.

Examples

align 5m, requests: rate(m("requests_total"))

Bins raw counter samples into five-minute intervals and emits the per-second rate of requests_total for each tag set and bin.

align 5m, requests: rate(m("requests_total")), memory_used: avg(m("memory_used"))

Aligns two different metrics in one step: rate on a counter and average on a gauge, sharing the same 5m grid and tag dimensions.

align 1m, frame(back: 10m), memory_used: avg(m("memory_used"))

Uses a sliding frame(back: 10m) so each 1m grid point summarizes the prior ten minutes of memory_used rather than only points inside that minute.

align 1m, frame_exact(back: 118s), memory_used: avg(m("memory_used"))

Same sliding-window idea as frame(back:…) but frame_exact keeps the lookback at exactly 118 seconds without the small rounding adjustment used for fuzzy frames.

align frame(back: 5m), requests: rate(m("requests_total"))

Omits an explicit period so bin width follows the workspace default resolution while still applying a five-minute trailing window for the rate of requests_total.

align options(bins: 100), memory_used: avg(m("memory_used"))

Lets Observe pick a human-readable step size that yields at most 100 buckets across the query window instead of fixing the duration yourself.

align options(bins: 100, min_bin: 5m), memory_used: avg(m("memory_used"))

Combines bins with min_bin so the auto-chosen width never shrinks below five minutes even when 100 bins would otherwise imply finer steps.

align options(bins: 1), memory_used: avg(m("memory_used"))

Forces a single bucket covering the entire query window, producing one aligned interval per time series for whole-window summaries.

align options(empty_bins: true), 5m, requests_per_second: rate(m("requests_total"))
make_col requests_per_second: if_null(requests_per_second, 0)

Turns on empty_bins so sparse series still get rows for every 5m slot, then replaces null rates with zero using if_null in a follow-up make_col.