Monitoring
Heartbeat Checks
Passive monitoring for cron jobs, background workers, and scheduled tasks. Instead of Beacon checking your endpoint, your service pings Beacon. If no ping arrives within the expected interval, it is treated as a failure.
What heartbeats do
HTTP monitors are active -- Beacon reaches out to your service. Heartbeat monitors are passive -- your service reaches out to Beacon. This reversal makes heartbeats ideal for tasks that do not expose an HTTP endpoint:
- Cron jobs and scheduled tasks
- Background workers and queue consumers
- Data pipeline stages
- Deployment scripts
- Database backup routines
- Certificate renewal processes
Each heartbeat monitor expects a ping at a regular interval. If the ping does not arrive before the deadline, Beacon treats it the same way as a failed HTTP check -- the consecutive failure counter increments, and once the threshold is exceeded, an auto-incident is created.
Creating a heartbeat monitor
Navigate to your status page, open the Monitors tab, and click Add Monitor. Select the Heartbeat type and fill in:
| Field | Description | Default |
|---|---|---|
| Name | A descriptive label, e.g. Nightly Backup |
-- |
| Interval | How often you expect a ping (in minutes) | 5 |
| Failure Threshold | Missed pings before an incident is created | 3 |
After creation, Beacon generates a unique ping URL for the monitor.
The ping URL
Each heartbeat monitor receives a unique URL in the following format:
POST https://usebeacon.pro/api/v1/heartbeat/{token}
The token is a unique, unguessable identifier generated when the monitor is created. No authentication headers are required -- the token itself serves as the credential. This makes it easy to use from minimal environments like cron or shell scripts.
Sending heartbeats
Send a POST request to the ping URL after your task completes. The response body is empty with a 200 status on success.
curl
curl -X POST https://usebeacon.pro/api/v1/heartbeat/abc123
Cron job
Append the curl command to the end of your cron entry so the ping only fires after the job completes:
# Run nightly backup at 2 AM, then ping Beacon
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -X POST https://usebeacon.pro/api/v1/heartbeat/abc123
PHP / Laravel
// In your Laravel scheduler (app/Console/Kernel.php)
$schedule->command('reports:generate')
->daily()
->after(function () {
Http::post('https://usebeacon.pro/api/v1/heartbeat/abc123');
});
Node.js
// After your job completes
await fetch('https://usebeacon.pro/api/v1/heartbeat/abc123', {
method: 'POST',
});
Python
import requests
# After your task completes
requests.post('https://usebeacon.pro/api/v1/heartbeat/abc123')
Ruby
require 'net/http'
# After your task completes
Net::HTTP.post(
URI('https://usebeacon.pro/api/v1/heartbeat/abc123'),
''
)
How failure works
Beacon tracks a next_check_at timestamp for each heartbeat monitor. This timestamp advances by the configured interval each time a ping is received.
The scheduled monitors:check command runs every minute. When it finds a heartbeat monitor whose next_check_at has passed without a new ping, it records a failure. The same threshold and auto-incident logic used by HTTP monitors applies:
- Consecutive missed pings are counted against the failure threshold
- Once the threshold is exceeded, an incident is created
- The linked component (if any) is set to
major_outage - Subscribers are notified
Recovery
Sending a ping to a heartbeat monitor that is in the down state immediately resolves the active auto-incident. The monitor returns to up, the linked component is restored to operational, and recovery notifications are sent to subscribers.
Practical examples
Laravel Scheduler with heartbeat
Monitor that your daily invoice job actually runs:
// app/Console/Kernel.php
$schedule->command('invoices:send')
->dailyAt('08:00')
->after(fn () => Http::post(
'https://usebeacon.pro/api/v1/heartbeat/inv-job-token'
));
Sidekiq worker
Confirm a recurring Sidekiq job completes:
class DataSyncWorker
include Sidekiq::Worker
def perform
sync_data_from_warehouse
# Ping Beacon on success
Net::HTTP.post(
URI('https://usebeacon.pro/api/v1/heartbeat/sync-token'),
''
)
end
end
Node.js scheduled task
Verify a Node.js cleanup task runs on schedule:
import cron from 'node-cron';
cron.schedule('0 */6 * * *', async () => {
await cleanupExpiredSessions();
// Ping Beacon on success
await fetch('https://usebeacon.pro/api/v1/heartbeat/cleanup-token', {
method: 'POST',
});
});