Skip to main content

Outcome monitoring for the jobs you already run

Not just "did it ping back." A finished process can still do no work. Post one HTTP receipt from five common runtimes. Laravel Horizon depth is optional on top.

Check in from five common runtimes

Same HTTP receipt. Laravel is the deep package for schedule, queue, and Horizon. All recipes

Works in every runtime

One HTTP receipt. Exit and outcome stay separate.

Post to /api/v1/ingest/cron when the job finishes. Include processed_records when the business result can be a count. Exit 0 with zero records can still open an incident.

  • ✓ curl / system cron
  • ✓ Node (fetch / node-cron / Bull)
  • ✓ Python (script / Celery)
  • ✓ Sidekiq / Ruby
  • ✓ GitHub Actions
Outcome receipt
statuscompleted
exit_code0
processed_records0 ← alert
runtimeany of five
Laravel deep package

Horizon internals when you run Laravel

The Composer package can read Horizon's Redis keys and attach schedule evidence. Not required for outcome monitoring on other runtimes.

  • ✓ Supervisor status per supervisor (not just "Horizon is running")
  • ✓ Paused detection
  • ✓ Failed jobs per minute with configurable threshold
  • ✓ Alerts when any supervisor goes down
Horizon status snapshot
statusrunning
supervisor-1running (3 workers)
supervisor-2down ← alert
failed / min4.2 (threshold: 5)
pausedno
Queue depths
QueueDepthFailedHealth
default50ok
emails1,2043alert
notifications120ok

Queue depth, before it becomes a customer complaint

Set per-queue thresholds for depth, failed count, and oldest job age. Get alerted before the backlog becomes a problem.

  • ✓ Depth threshold per queue
  • ✓ Failed count threshold
  • ✓ Oldest job age (wait time) alert
  • ✓ Works with Redis and database queue drivers

Run history: exit code and business result

Every receipt records status, exit code, and outcome metrics. On Laravel, the package can also attach scheduler events automatically. Everywhere else, wrap the job and POST the same JSON.

  • ✓ Exit code per run
  • ✓ Outcome column separate from process status
  • ✓ "Late" detection when named jobs miss the schedule
  • ✓ Historical chart per command
Scheduled commands
CommandLast runStatus
inspire6h agook
send-invoices5d agook
cleanup-old-logs23h ago⚠ late

Crontinel Agent: run commands from the dashboard

A lightweight daemon (Laravel, Node, or Python) that connects to your app and executes commands you schedule from the cloud. Refuses to run anything until you explicitly allowlist it; nothing runs by default.

Alerts that go where you work

Fires when something breaks. Resolves automatically when it recovers. No noise.

Slack
Webhook or app integration
Email
Single or multiple recipients
PagerDuty
Full incident lifecycle
Webhook
Any endpoint you choose
Discord
Post to a server channel
Microsoft Teams
Post to a team channel
Telegram
Bot API, direct to a chat

Five runtimes. One ingest API. MCP for assistants.

HTTP receipt for every stack. Laravel package when you want schedule and Horizon depth.

curl / cron Node Python Sidekiq GitHub Actions Laravel package REST API MCP Webhook alerts

Frequently asked questions

Does Crontinel work without Laravel?

Yes. Outcome monitoring uses one HTTP receipt. curl, Node, Python, Sidekiq, and GitHub Actions are first-class. Horizon and queue freshness are optional Laravel package features. Absence of a Horizon snapshot outside Laravel is normal, not an incident.

How does Crontinel monitor Horizon internals?

Crontinel reads Horizon's Redis keys directly, the same data source the Horizon dashboard uses. This means it sees actual supervisor states, actual pause status, and actual failed-jobs-per-minute rates, not just whether an HTTP health endpoint returned 200. This approach catches scenarios where Horizon reports "running" at the top level while an individual supervisor handling a critical queue has silently crashed.

What queue drivers does Crontinel support?

Crontinel supports the Redis and database queue drivers. Redis is the recommended driver for production Horizon setups, and Crontinel reads queue depths and failed counts directly from Redis. For apps using the database driver, Crontinel queries the jobs and failed_jobs tables. SQS and other drivers are not currently supported.

Does cron tracking require code changes to my scheduled commands?

No. Crontinel hooks into Laravel's built-in scheduler events (ScheduledTaskStarting, ScheduledTaskFinished, ScheduledTaskFailed) automatically after installation. Every command defined in your schedule() method is tracked with its exit code and duration. No wrapping, no per-command changes needed.

How are alerts deduplicated?

Crontinel applies a 5-minute cooldown per alert condition. If a queue depth stays above its threshold, you receive one alert, not one per polling cycle. The alert resolves automatically when the condition clears, at which point you receive a recovery notification. This prevents alert fatigue during extended incidents while still giving you clear start and end signals.

Is the OSS package free forever?

Yes. The core Crontinel package is MIT licensed and will remain free forever. You can self-host the full monitoring dashboard, configure Slack or email alerts, and track unlimited cron runs and queue depths with no subscription required. The paid SaaS tier adds multi-app dashboards, longer history retention, and team access for engineering organizations that want managed infrastructure.

Advertise the receipt in your job

Five common runtimes post the same outcome body: curl, Node, Python, Sidekiq, and GitHub Actions. Laravel apps can add the Composer package for schedule, queue, and Horizon.

curl -X POST "$CRONTINEL_API_URL/api/v1/ingest/cron" \
  -H "Authorization: Bearer $CRONTINEL_INGEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command":"nightly-import","status":"completed","exit_code":0,"outcomes":{"metrics":{"processed_records":0}}}'
Start free, no credit card