Monitoring cron
Schedule the monitoring endpoint correctly for 24-hour background checks.
API reference
Monitoring cron
Continuous monitoring depends on an external scheduler calling the cron endpoints on a regular cadence. PreFlight ships with two cron endpoints, both authenticated with the same CRON_SECRET bearer token. You can drive them from Vercel Cron, cron-job.org, GitHub Actions, or any scheduler that can send an authenticated HTTP request.
The monitoring route is a single self-throttling endpoint: every job inside it (Sentinel, 24-hour Monitoring, Revenue Ledger Watch, custom checks, Vercel Watch, Data Integrity Guard, Burn Radar, and scheduled site audits) checks its own due-time, so calling it more often never double-runs work — it just keeps everything current.
Endpoints
/api/cron/monitoringPrimary scheduler entry point. POST is also accepted for manual or legacy scheduler compatibility.
/api/cron/gsc-syncDaily Google Search Console rank-data sync for the SEO Suite Rank Tracker.
GET /api/cron/monitoring
Authorization: Bearer <CRON_SECRET>
Returns 401 when the bearer token does not match CRON_SECRET. The monitoring route returns 503 when CRON_SECRET or SUPABASE_SERVICE_ROLE_KEY is unset.
Required environment variables
| Variable | Purpose |
|---|---|
CRON_SECRET | Bearer token your scheduler sends; must match server env |
SUPABASE_SERVICE_ROLE_KEY | Server-side reads and writes for samples, alerts, and activity |
RESEND_API_KEY + branded sender | Email alert delivery when email channels are configured |
Optional alert channels (Slack, Discord, PagerDuty, OpsGenie, Teams, webhooks) use credentials saved per workspace in encrypted alert channel configs — not additional cron env vars.
Setting up cron-job.org
cron-job.org can run as many cron jobs as you want, so you can schedule each endpoint independently. For each job:
Create a cron job pointing at the full URL, for example
https://your-app.com/api/cron/monitoring.Add the auth header. Under Advanced → Headers, add
Authorizationwith valueBearer YOUR_CRON_SECRET(the same value as the server'sCRON_SECRET).Set the schedule per the table below.
Save and run once to confirm a
200response. A401means the header/secret is wrong;503means a server env var is missing.
Recommended jobs
| Job | URL | Schedule | Why |
|---|---|---|---|
| Monitoring (everything) | /api/cron/monitoring | every 5–10 minutes (*/5 * * * *) | Drives Sentinel, monitoring sessions, revenue, Vercel Watch, custom checks, Data Integrity Guard, Burn Radar, and due site audits |
| GSC rank sync | /api/cron/gsc-sync | daily (0 3 * * *) | Pulls the last 28 days of Search Console performance |
One monitoring job is enough
Because every job inside /api/cron/monitoring self-throttles on its own cadence (Sentinel next-sample time, audit interval, revenue cadence, etc.), a single cron-job.org entry calling it every 5–10 minutes runs all of them correctly. Add the GSC job separately only if you use the Rank Tracker.
What each monitoring tick does
Monitoring sessions. Loads active 24-hour sessions, records health samples, completes expired sessions, and triggers alerts after repeated failures.
Sentinel. Samples due Sentinel projects up to the batch limit, records outcomes, schedules next sample times, and emits threshold alerts.
Revenue Ledger Watch. Runs due Stripe-to-Supabase reconciliation snapshots on the configured cadence.
Custom checks. Executes scheduled HTTP assertions defined in Custom Checks.
Vercel Watch. Probes connected Vercel projects for deployment and domain drift when integrations are due.
Scheduled site audits. Runs any due site audits (AI Visibility, Performance, Accessibility, Domain, Email, Security). Opening the Site Audits page auto-creates daily passive schedules for a project, so these populate without manual runs.
Data Integrity Guard, Revenue Guard, and Burn Radar. Captures due metadata baselines, runs due shadow-checkout guards, and recomputes usage/spend forecasts.
Activity and cost guards. Records operational events for Incidents and the Flight Recorder; prunes cost logs and enforces sample rate limits.
Provider probes during monitoring
When a monitoring session or Sentinel sample runs provider probes, PreFlight uses a focused probe key set per integration — for example Stripe webhook registry, Supabase RLS audit, and Vercel deployment status — rather than the full check suite.
Response shape
Successful ticks return a JSON summary of work performed:
{
"sampled": 3,
"completed": 1,
"sentinelSampled": 12,
"revenueChecked": 2,
"vercelWatched": 1,
"customCheckSampled": 0,
"alertsAttempted": 1,
"scheduledTasksRan": 4
}
Exact field names match the implementation response. Use server logs and Flight Recorder activity when debugging missed samples.
Deployment on Vercel
If you host on Vercel instead of cron-job.org, add cron entries in vercel.json:
{
"crons": [
{ "path": "/api/cron/monitoring", "schedule": "*/10 * * * *" },
{ "path": "/api/cron/gsc-sync", "schedule": "0 3 * * *" }
]
}
Set CRON_SECRET in Vercel project environment variables. Vercel sends it automatically as Authorization: Bearer … on cron invocations when configured.
Keep cadence at 10 minutes or faster
Sentinel next-sample scheduling and failure-window logic assume the scheduler runs at least every 10 minutes. Slower cadences delay alerts and can miss short-lived regressions during launch windows.
Self-hosted schedulers
Any scheduler that can send authenticated HTTP requests works:
- cron-job.org (see above)
- GitHub Actions on a cron schedule
- Cloudflare Workers Cron Triggers
- AWS EventBridge → Lambda
- systemd timer + curl
Requirements:
- Call
GETorPOSTon/api/cron/monitoring. - Send
Authorization: Bearer <CRON_SECRET>. - Run at 10-minute intervals or faster.
Rate limiting
The cron route enforces 24 requests per minute per origin (cron_monitoring bucket). Normal 10-minute scheduling stays well under this limit.
Troubleshooting
| Symptom | Check |
|---|---|
| 401 Unauthorized | CRON_SECRET mismatch between scheduler and server env |
| 503 Service unavailable | Missing CRON_SECRET or SUPABASE_SERVICE_ROLE_KEY |
| Sentinel samples stop | Project paused, cadence unset, or cron not firing |
| Revenue Watch never runs | Stripe/Supabase not connected or mapping incomplete |
| Alerts not delivered | Alert channel disabled, rate limited, or active silence window |
