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

# Heartbeats

> Noticing work that has stopped running rather than started failing.

A heartbeat watches something that is supposed to happen regularly. The thing
being watched calls a URL when it finishes; **nothing arriving is the signal**.

This is the only way to notice work that has quietly stopped. A nightly backup
script that no longer runs produces no failure, no output and no error, and is
indistinguishable from one that is running fine.

## Setting one up

Give it a name, say how often it **runs**, and say how long after that you want
to be **told**.

The second number is grace. A run that takes a while, or a machine whose clock
has drifted, should not raise an alert — so a job that runs hourly with fifteen
minutes of grace is late at seventy-five minutes, not at sixty-one.

Shipways gives you an address. Call it at the **end** of the work, not the
start: the point is to hear that it finished.

```
0 3 * * * /usr/bin/php8.4 artisan backup:run && curl -fsS https://.../webhooks/heartbeat/<token>
```

`&&` rather than `;`, so a failed job does not report success.

Both `GET` and `POST` are accepted, because the way these lines actually get
written is with `curl`.

## It does not have to be a Shipways job

Anything that can make an HTTP call when it finishes can be watched: a job on a
machine Shipways does not manage, a GitHub Action, a partner's nightly import.
Heartbeats are deliberately not tied to
[scheduled jobs](/processes/scheduled-jobs).

## Missing one

A heartbeat whose deadline passes [opens an alert](/alerts).

A heartbeat that has **never** been called has no deadline to miss, and shows
as waiting for its first call rather than as late. Set one up, then run the job
once by hand to confirm the address is right.

## Removing one

The address stops answering, so whatever was calling it needs changing too — a
`curl` to a dead heartbeat with `-f` will start failing the job it was appended
to.
