> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Heartbeats

> Continuously verify system health using Rootly Heartbeats and automatically trigger alerts on missed pings from cron jobs, schedulers, and background workers.

## Overview

Heartbeats allow you to monitor critical systems by requiring them to “check in” on a regular cadence.\
If a heartbeat fails to ping within the expected interval, Rootly automatically triggers an alert and notifies the appropriate on-call responders.

This ensures:

* Early detection of system failures
* Automatic paging when checks go silent
* Reliable uptime verification across services
* Zero reliance on external monitoring tools for liveness checks

***

## How Heartbeats Work

Each Heartbeat cycles through three statuses:

* **waiting** — newly created or recently updated; awaiting first ping
* **active** — successfully pinged and within its valid interval
* **expired** — missed its expected check-in; triggers a Heartbeat Alert

Each heartbeat is **disabled by default**. When enabled, Rootly tracks pings and expiration windows.

When a ping is received:

* `last_pinged_at` is updated
* `expires_at` is set to `now + interval`
* Status becomes **active**
* If transitioning from non-active → active, Rootly **resolves all open heartbeat alerts**

***

## Creating & Configuring Heartbeats

<Steps>
  <Step title="Step 1: Create a Heartbeat">
    Navigate to **On-Call → Heartbeats** and click **+ New Heartbeat**.

    Configure each field:

    <ParamField path="Name" type="string" required>
      A unique name for this heartbeat within the team.
    </ParamField>

    <ParamField path="Description" type="string">
      Optional context — what this heartbeat covers and why it exists.
    </ParamField>

    <ParamField path="Notification Target" type="Escalation Policy | Service | Team (Group) | User" required>
      Who or what gets paged when the heartbeat expires. The target determines which escalation path runs.
    </ParamField>

    <ParamField path="Alert Summary" type="string (1–100 chars)" required>
      The summary that appears on the generated heartbeat alert.
    </ParamField>

    <ParamField path="Alert Urgency" type="configured urgency">
      Optional but recommended — controls how the missed-ping alert is escalated. Falls back to the team default if unset.
    </ParamField>

    <ParamField path="Expected Ping Interval" type="interval + unit">
      How often the heartbeat expects a ping. Interval accepts `1–300` (minimum `60` when the unit is seconds); the unit is one of seconds, minutes, hours, or days.
    </ParamField>

    Heartbeats start in **waiting** and **disabled** until explicitly enabled.
  </Step>

  <Step title="Step 2: Enable and Activate the Heartbeat">
    Enabling a heartbeat begins the monitoring cycle. Note:

    * Changing **interval**, **interval unit**, or **enabling** a heartbeat resets it back to **waiting**
    * A heartbeat becomes **active** only after its **first successful ping**
  </Step>
</Steps>

***

## Pinging Heartbeats

Systems can ping heartbeats using **HTTP** or **email**.\
Both methods behave identically: they reset the timer and, if previously expired, will **resolve all heartbeat alerts**.

### HTTP Ping (Recommended)

Use the automatically generated ping URL:

```bash theme={null}
curl -X POST https://api.rootly.com/v1/heartbeats/{heartbeat_id}/ping \
--header 'Authorization: Bearer {heartbeat_token}'
```

Replace `{heartbeat_id}` with your Heartbeat’s UUID and `{heartbeat_token}` with your Heartbeat's Auth token.\
Both are displayed directly in the Heartbeat’s configuration page.

<Info>
  Authorization header is required to send HTTP pings.
</Info>

<Info>
  HTTP pings are ideal for scripts, cron jobs, containers, CI pipelines, and any system capable of making HTTP requests.
</Info>

***

### Email Ping

Every Heartbeat is also assigned a **unique email address**:

```text theme={null}
heartbeat-<unique_key>@<your-inbound-domain>
```

Sending *any* email to this address counts as a valid ping.

**Common use cases:**

* Legacy systems that only support email notifications
* Backup/cron jobs that already send “success” emails
* Air-gapped or restricted systems that cannot perform HTTP requests

Behavior:

* Email subject/body do **not** matter
* Each valid email resets the Heartbeat’s timer
* Invalid addresses return a bounce notification

<Note>
  You can find the Heartbeat’s email address directly in its configuration panel.
</Note>

***

## Heartbeat Expiration & Recovery

### When Does a Heartbeat Expire?

A Heartbeat transitions to **expired** when:

```text theme={null}
current_time > expires_at
```

When expired:

* A **Heartbeat Alert** is created
* Routing rules determine who gets paged
* Escalation Policies and Alert Urgency define notification behavior

***

### Automatic Recovery

If an expired heartbeat receives a ping:

1. Status transitions **expired → active**
2. All open Heartbeat Alerts are **automatically resolved**
3. A recovery event is added to the alert timeline

This avoids noisy follow-up alerts and validates system recovery.

***

## Who Gets Paged for a Missed Heartbeat

Every Heartbeat must be configured with **one notification target**:

* **Escalation Policy**
* **Service**
* **Team (Group)**
* **User**

Rootly applies your workspace's:

* Escalation rules
* Working hours
* Alert urgency
* The paged responder's [notification rules](/on-call/on-call-notifications), which decide which delivery methods reach them

Missed pings create a heartbeat alert that follows the routing of the target you chose.

***

## Best Practices

* Use **short intervals** (1–5 minutes) for critical services
* Set **High urgency** for production-impacting checks
* Use **email pings** for legacy or offline systems
* Name Heartbeats clearly (for example, `api-liveness`, `db-backup-success`)
* Use separate Heartbeats for independent components
* Review heartbeat alerts weekly to detect flapping or missing pings

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Heartbeat stays in 'waiting'" icon="hourglass">
    * Heartbeat may not be **enabled**
    * Interval or unit was recently changed → resets to waiting
    * No valid pings received yet
    * Verify ping URL or email address is correct
  </Accordion>

  <Accordion title="Heartbeat never expires" icon="infinity">
    * Interval may be too large
    * System may be sending frequent pings
    * Verify whether alert resolution is immediately resetting intervals
  </Accordion>

  <Accordion title="Alerts do not resolve after pings" icon="bell-slash">
    * Check whether status transitioned `expired → active`
    * Ensure ping reached the correct Heartbeat ID
    * Review timeline for recovery events
  </Accordion>

  <Accordion title="Email pings aren’t registering" icon="envelope">
    * Inbound email domain may not be configured
    * MX records could be missing or misconfigured
    * Invalid email formats will bounce
  </Accordion>
</AccordionGroup>

***

## Related Pages

<CardGroup cols={3}>
  <Card title="Alerts Overview" icon="bell" href="/alerts/alerts">
    Missed pings create heartbeat alerts — they flow through the same routing and paging pipeline.
  </Card>

  <Card title="Escalation Policies" icon="stairs" href="/on-call/escalation-policies">
    Where a heartbeat alert is routed once it fires — the same escalation logic every other alert follows.
  </Card>

  <Card title="Alert Urgency" icon="gauge-high" href="/alerts/alert-urgency">
    Each heartbeat carries an urgency that decides how aggressively responders are paged.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.