Your nightly database backup stopped running six days ago. The just backup recipe is still in your Justfile, your CI config still references it, and nobody got an error — the scheduled job just quietly disappeared from the execution log. Just is a fantastic command runner, but it has no built-in mechanism to tell you when a recurring task stops firing.
This tutorial shows you how to instrument Just recipes with Vigilmon heartbeat monitors so silent failures become loud, immediate alerts.
What You'll Cover
- Heartbeat monitoring for scheduled Just recipes
- Detecting recipes that stop running entirely
- Monitoring multi-step task pipelines in Just
- CI integration with heartbeat verification
- Alert channel setup for Just task failures
Prerequisites
- Just installed (
brew install just,cargo install just, or your OS package manager) - A project with a Justfile containing recurring or scheduled recipes
- A free account at vigilmon.online
Why Just Needs External Monitoring
Just is a command runner, not a scheduler. It executes recipes when you call them — it does not retry, log completion history, or alert you if a recipe was skipped. Common silent failure modes include:
- A cron job calling
just backupfails to start (wrong user, missing PATH, env var not set) - A CI pipeline drops a
just deploystep after a workflow refactor - A recipe depends on a service that went offline, causing it to exit silently
- An
&&chain in a recipe stops mid-way due to a non-zero exit, but the outer caller ignores the exit code
Vigilmon's heartbeat pattern catches all of these: your recipe sends a ping at the end, and if Vigilmon doesn't receive the ping within the expected window, you get alerted.
Step 1: Create a Heartbeat Monitor in Vigilmon
- Log in to Vigilmon and click New Monitor → Heartbeat.
- Give it a descriptive name like
Nightly Backup — just backup. - Set the Expected interval to match your recipe's schedule. For a nightly cron, use 24 hours. Add a 20–30% buffer: a workflow that runs at 02:00 UTC can drift to 02:15, so set the grace period accordingly.
- Set the Grace period to 30 minutes for short-interval recipes or 1 hour for daily ones.
- Save and copy the Ping URL — it looks like
https://vigilmon.online/api/heartbeat/<unique-id>.
Step 2: Add a Heartbeat Ping to a Recipe
The pattern is simple: run the real work, then curl the Vigilmon endpoint only on success.
# Justfile
# Environment variable — set in your shell, .env, or CI secrets
vigilmon_backup_url := env_var_or_default("VIGILMON_BACKUP_URL", "")
# Nightly database backup with heartbeat monitoring
backup:
#!/usr/bin/env bash
set -euo pipefail
echo "Starting database backup..."
pg_dump "$DATABASE_URL" | gzip > "/backups/db-$(date +%Y%m%d).sql.gz"
echo "Backup complete. Pinging Vigilmon..."
curl -fsS -X POST "{{vigilmon_backup_url}}" \
--max-time 10 \
--retry 3 \
--retry-delay 2
echo "Heartbeat sent."
Key points:
set -euo pipefail— the script exits immediately on any error, so thecurlping is only reached if the backup succeeded.--retry 3— transient network issues won't cause a false "missed heartbeat" alert.env_var_or_default— the recipe still works locally without the secret; the curl call is a no-op when the URL is empty (curl exits non-zero on an empty URL, but|| trueor a conditional guard handles that).
Guard the ping when the URL is absent
For local development where VIGILMON_BACKUP_URL is not set:
backup:
#!/usr/bin/env bash
set -euo pipefail
pg_dump "$DATABASE_URL" | gzip > "/backups/db-$(date +%Y%m%d).sql.gz"
if [ -n "${VIGILMON_BACKUP_URL:-}" ]; then
curl -fsS -X POST "$VIGILMON_BACKUP_URL" --max-time 10 --retry 3
fi
This way the recipe is safe to run locally and only pings Vigilmon in environments where the secret is configured.
Step 3: Monitor a Multi-Step Pipeline
Just recipes often chain commands. Monitor the whole pipeline, not individual steps:
deploy:
#!/usr/bin/env bash
set -euo pipefail
echo "Building..."
just build
echo "Running migrations..."
just migrate
echo "Deploying to production..."
just _push-to-prod
echo "Running smoke tests..."
just smoke-test
# All steps succeeded — send heartbeat
curl -fsS -X POST "$VIGILMON_DEPLOY_URL" --max-time 10 --retry 3
echo "Deploy complete and heartbeat sent."
build:
cargo build --release
migrate:
./scripts/run-migrations.sh
_push-to-prod:
rsync -avz target/release/app user@prod:/opt/app/
smoke-test:
./scripts/smoke-test.sh
If any step in the chain returns a non-zero exit code, set -euo pipefail aborts execution and the heartbeat ping is never sent. Vigilmon alerts you after the grace period.
Step 4: Wire Up Your Cron Job
The most common trigger for Just recipes is a system cron job. Here's a typical setup:
# /etc/cron.d/app-tasks
# Backup every night at 02:00
0 2 * * * app-user /usr/local/bin/just --justfile /opt/app/Justfile backup >> /var/log/app-backup.log 2>&1
# Deploy every weekday at 10:00
0 10 * * 1-5 deploy-user /usr/local/bin/just --justfile /opt/app/Justfile deploy >> /var/log/app-deploy.log 2>&1
Important: cron runs with a minimal environment. Make sure VIGILMON_BACKUP_URL is set in the cron job's environment or loaded from a file:
0 2 * * * app-user bash -c 'source /opt/app/.env && /usr/local/bin/just --justfile /opt/app/Justfile backup' >> /var/log/app-backup.log 2>&1
Step 5: CI Integration
For GitHub Actions or GitLab CI pipelines that call Just recipes, add the heartbeat URL as a CI secret and let the recipe handle pinging:
# .github/workflows/nightly.yml
name: Nightly Tasks
on:
schedule:
- cron: "0 2 * * *"
jobs:
run-tasks:
runs-on: ubuntu-latest
env:
VIGILMON_BACKUP_URL: ${{ secrets.VIGILMON_BACKUP_URL }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- uses: actions/checkout@v4
- name: Install Just
uses: extractions/setup-just@v2
- name: Run backup
run: just backup
The recipe itself sends the heartbeat — no extra CI step needed. If just backup fails, the CI step fails and the heartbeat is never sent.
Step 6: Monitor Recipe Execution Time
For long-running recipes, you may also want to detect when they take too long — which can signal a hung process or resource exhaustion. Use Vigilmon's max duration setting:
- In your heartbeat monitor settings, set a Max expected duration (e.g., 10 minutes for a recipe that normally takes 2).
- Send the ping with a start timestamp by pinging at the beginning of the recipe (as a "start" signal) and again at the end (as a "success" signal).
A simpler approach is to set your cron grace period tighter than the recipe's max expected runtime — if the recipe takes more than 12 minutes but normally takes 3, Vigilmon will fire an alert on the next interval check.
Step 7: Configure Alert Channels
In Vigilmon, go to Notifications → New Channel and configure:
- Email — immediate alert when a heartbeat is missed
- Slack webhook — post to
#alertsor#ops
When just backup stops pinging:
🔴 MISSED HEARTBEAT: Nightly Backup — just backup
Last ping: 26 hours ago
Expected interval: 24 hours
When it recovers:
✅ HEARTBEAT RECOVERED: Nightly Backup — just backup
Gap: 26 hours
What You're Now Catching
| Silent failure mode | How Vigilmon detects it |
|---|---|
| Cron job fails to start (wrong PATH, missing env) | No ping arrives → alert after grace period |
| Recipe exits early due to a command failure | set -euo pipefail prevents ping → alert |
| CI pipeline drops the Just step after a refactor | No ping on CI run → alert |
| Dependent service is offline, recipe hangs or exits | Ping never sent → alert |
| Just not found in cron's PATH | Recipe never runs → no ping → alert |
Just makes command orchestration clean and readable — but it has no opinion on whether your recipes actually ran. Vigilmon's heartbeat monitors fill that gap: a definitive external signal that tells you when your Justfile tasks stop working.
Start monitoring your Just recipes today — register free at vigilmon.online.