Aggregations

Sum, average, and percentile calculations across a range.

Aggregations compute a single value from the numbers attached to your events. Use them when the question is about amounts, durations, or distributions rather than raw counts.

Supported aggregations

  • count: number of rows
  • count_unique: number of distinct values for a field
  • sum: total across the range
  • avg: arithmetic mean
  • min / max: smallest and largest value
  • p50, p90, p95, p99: percentiles

For simple counting, count() is enough. Use aggregate() when you need a value or a percentile.

The aggregate call

Aggregate numeric fields on your events. Event data lives under data, so a field like data.amount aggregates cleanly:

Sum

typescript
const revenue = await vanta.aggregate({
  filters: filter('type', 'equals', 'purchase'),
  aggregations: [{ field: 'data.amount', operation: 'sum' }],
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

Average

typescript
const averageOrder = await vanta.aggregate({
  filters: filter('type', 'equals', 'purchase'),
  aggregations: [{ field: 'data.amount', operation: 'avg' }],
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

Percentiles

Use percentiles to describe a distribution. For example, p95 of request duration is the value that 95% of requests stayed at or under:

typescript
const p95 = await vanta.aggregate({
  filters: filter('type', 'equals', 'api.request'),
  aggregations: [{ field: 'data.durationMs', operation: 'p95' }],
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})

Counters

Counters accumulate changes with increments and decrements. A sum on a counter returns the net change over the range: increments minus decrements.

typescript
const netConnections = await vanta.aggregate({
  aggregations: [{ field: 'data.activeConnections', operation: 'sum' }],
  time: timeRange('2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z'),
})