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
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
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
| Queue | Depth | Failed | Health |
|---|---|---|---|
| default | 5 | 0 | ok |
| emails | 1,204 | 3 | alert |
| notifications | 12 | 0 | ok |
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
| Command | Last run | Status |
|---|---|---|
| inspire | 6h ago | ok |
| send-invoices | 5d ago | ok |
| cleanup-old-logs | 23h 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.
Five runtimes. One ingest API. MCP for assistants.
HTTP receipt for every stack. Laravel package when you want schedule and Horizon depth.
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}}}'