Overview
Aggregations are declared in your subgraph schema through two complementary types:- Timeseries type: Stores raw data points with timestamps
- Aggregation type: Defines how raw data is aggregated over time intervals
Defining Timeseries
A timeseries entity stores individual data points with automatic timestamps:Marks the type as a timeseries. These entities are immutable and append-only.
Automatically set by Graph Node in insertion order. Must be of type
Int8.Automatically set by Graph Node to the current block timestamp. User-provided values are silently overridden.
Timeseries Characteristics
- Immutable: Once created, timeseries entities cannot be updated or deleted
- Automatic IDs: The
idfield is set automatically in ascending order - Automatic timestamps: The
timestampfield is always set to block timestamp - Efficient storage: Optimized for append-only operations
Defining Aggregations
Aggregations compute statistics over timeseries data at specified time intervals:Marks the type as an aggregation with two required arguments:
intervals: Array of time intervals ("hour"or"day")source: Name of the timeseries type to aggregate
Automatically set by Graph Node. Set to the
id of one of the source data points (unspecified which).Automatically set to the beginning of the aggregation time interval.
Aggregation Functions
The@aggregate directive supports these functions:
Sum of all values in the interval.
Number of data points in the interval.
Minimum value in the interval.
Maximum value in the interval.
First value in the interval (by timeseries
id ordering).Last value in the interval (by timeseries
id ordering).Dimensions
Dimensions are non-aggregated fields used to group data. They enable multi-dimensional aggregations:- Fields without
@aggregateare dimensions - Each unique combination of dimension values creates a separate aggregation series
- In the example above, each token gets its own hourly and daily statistics
Cumulative Aggregations
By default, aggregations compute values for each time interval independently. Cumulative aggregations compute running totals across all intervals:When
true, aggregates over the entire timeseries up to the end of the current interval.Aggregation Expressions
Thearg parameter can be a field name or a SQL expression:
Supported Expression Syntax
Expressions use SQL syntax with these supported features:Operators
Operators
- Arithmetic:
+,-,*,/,%,^ - Comparison:
=,!=,<,<=,>,>= - Logical:
and,or,not - Other:
is [not] {null|true|false},is [not] distinct from
Math Functions
Math Functions
abs(x): Absolute valueceil(x),ceiling(x): Round upfloor(x): Round downdiv(x, y): Integer divisionmod(x, y): Modulopower(x, y): Exponentiationgcd(x, y): Greatest common divisorlcm(x, y): Least common multiplesign(x): Sign (-1, 0, or 1)
Conditional Functions
Conditional Functions
coalesce(x, y, ...): First non-null valuenullif(x, y): NULL if x equals ygreatest(x, y, ...): Maximum valueleast(x, y, ...): Minimum valuecase when ... then ... else ... end: Conditional expression
Querying Aggregations
Graph Node creates top-level query fields for each aggregation:Basic Aggregation Query
Time interval to query:
"hour" or "day" (must match intervals defined in schema).Whether to include the current, partially filled bucket:
exclude: Only return completed, rolled-up buckets (default)include: Also return in-progress bucket computed on-the-fly
Filtering Aggregations
Filter by dimensions and timestamp ranges:Available Timestamp Filters
Exact timestamp match (microseconds since epoch).
Greater than or equal to timestamp.
Greater than timestamp.
Less than or equal to timestamp.
Less than timestamp.
Timestamp in list.
Timestamps are strings containing microseconds since Unix epoch.Example:
"1704164640000000" = 2024-01-02T03:04:00ZConvert from seconds: seconds * 1000000Current Bucket
By default, aggregation queries return only completed, rolled-up buckets. Settingcurrent: include adds the in-progress bucket:
exclude: Only returns buckets whose time interval has ended and been rolled upinclude: Adds one additional bucket computed on-the-fly from unrolled source data- The current bucket covers from the last completed bucket to the most recent data point
Nested Aggregation Queries
Thecurrent argument works on nested aggregation fields:
Complete Example
Here’s a comprehensive example showing timeseries and aggregations for DEX trading data:schema.graphql
Query Examples
Sorting Behavior
Aggregations have a default sort order:- Sorted by
timestampandidin descending order by default - Returns most recent buckets first
- Can be overridden with
orderByandorderDirection
Best Practices
- Choose appropriate intervals: Use hourly for recent data, daily for historical trends
- Use dimensions wisely: Each dimension combination creates separate aggregation series
- Leverage cumulative aggregations: Useful for running totals and lifetime metrics
- Filter by timestamp: Always specify timestamp ranges to limit data scanned
- Monitor aggregation lag: Current buckets may not reflect all recent data until rollup completes
- Use expressions for computed metrics: Calculate derived values at aggregation time
Next Steps
- Learn about time-travel queries for historical state
- Review query syntax for advanced filtering
- Explore GraphQL API overview for basic concepts

