---
title: Heartbeat aggregation overview | Tiger Data Docs
description: Determine system liveness from timestamped heartbeats with heartbeat_agg functions
---

Determine the overall liveness of a system from a series of timestamped heartbeats and a liveness interval. This aggregate can be used to report total uptime or downtime as well as report the time ranges where the system was live or dead.

You can combine multiple heartbeat aggregates to determine the overall health of a service. For example, the heartbeat aggregates from a primary and standby server could be combined to see if there was ever a window where both machines were down at the same time.

## Two-step aggregation

This group of functions uses the two-step aggregation pattern.

Rather than calculating the final result in one step, you first create an intermediate aggregate by using the aggregate function.

Then, use any of the accessors on the intermediate aggregate to calculate a final result. You can also roll up multiple intermediate aggregates with the rollup functions.

The two-step aggregation pattern has several advantages:

1. More efficient because multiple accessors can reuse the same aggregate
2. Easier to reason about performance, because aggregation is separate from final computation
3. Easier to understand when calculations can be rolled up into larger intervals, especially in window functions and [continuous aggregates](/build/continuous-aggregates/create-a-continuous-aggregate/index.md)
4. Can perform retrospective analysis even when underlying data is dropped, because the intermediate aggregate stores extra information not available in the final result

To learn more, see the [blog post on two-step aggregates](https://www.timescale.com/blog/how-postgresql-aggregation-works-and-how-it-inspired-our-hyperfunctions-design).

## Functions in this group

### Aggregate

- [`heartbeat_agg()`](/reference/toolkit/state-tracking/heartbeat_agg/heartbeat_agg/index.md): aggregate heartbeat data into an intermediate form for further computation

### Accessors

- [`uptime()`](/reference/toolkit/state-tracking/heartbeat_agg/uptime/index.md): get the total uptime from the aggregate
- [`downtime()`](/reference/toolkit/state-tracking/heartbeat_agg/downtime/index.md): get the total downtime from the aggregate
- [`interpolated_uptime()`](/reference/toolkit/state-tracking/heartbeat_agg/interpolated_uptime/index.md): get the total uptime, interpolating values at the boundary
- [`interpolated_downtime()`](/reference/toolkit/state-tracking/heartbeat_agg/interpolated_downtime/index.md): get the total downtime, interpolating values at the boundary
- [`live_at()`](/reference/toolkit/state-tracking/heartbeat_agg/live_at/index.md): determine if the system was live at a given time
- [`live_ranges()`](/reference/toolkit/state-tracking/heartbeat_agg/live_ranges/index.md): get all time ranges when the system was live
- [`dead_ranges()`](/reference/toolkit/state-tracking/heartbeat_agg/dead_ranges/index.md): get all time ranges when the system was dead
- [`num_live_ranges()`](/reference/toolkit/state-tracking/heartbeat_agg/num_live_ranges/index.md): count the number of live ranges
- [`num_gaps()`](/reference/toolkit/state-tracking/heartbeat_agg/num_gaps/index.md): count the number of gaps (downtime periods)
- [`trim_to()`](/reference/toolkit/state-tracking/heartbeat_agg/trim_to/index.md): trim the aggregate to a specific time range

### Mutator

- [`interpolate()`](/reference/toolkit/state-tracking/heartbeat_agg/interpolate/index.md): interpolate the state at interval boundaries

### Rollup

- [`rollup()`](/reference/toolkit/state-tracking/heartbeat_agg/rollup/index.md): combine multiple intermediate aggregates
