Monitor a Vercel Cron Job
Copy the schedule from vercel.json, set the zone to UTC, then ping from the route handler.
1. Create the monitor from vercel.json
Paste the schedule value and set the zone to UTC, because Vercel always reads cron schedules in UTC.
{
"crons": [{ "path": "/api/nightly-backup", "schedule": "0 2 * * *" }]
}2. Set the grace period for your plan
On Pro and Enterprise, Vercel invokes the job within the scheduled minute, so a few minutes of grace plus the job's own runtime is enough.
On Hobby, a job runs once a day at most and can be invoked at any point within the scheduled hour. Set the grace period to more than an hour, or the monitor will alert on normal runs.
3. Ping from the route handler
Add the ping URL as an environment variable named CRONWIZE_PING_URL. Await each ping: a function can stop once it has responded.
import type { NextRequest } from "next/server";
const PING = process.env.CRONWIZE_PING_URL!;
// A failed ping is swallowed, so that it never fails the job.
async function ping(signal: string, body?: string) {
await fetch(PING + signal, {
method: "POST",
body,
signal: AbortSignal.timeout(10_000),
}).catch(() => undefined);
}
export async function GET(request: NextRequest) {
if (request.headers.get("authorization") !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
await ping("/start");
try {
await runBackup();
await ping("");
return Response.json({ ok: true });
} catch (error) {
await ping("/fail", String(error));
return Response.json({ ok: false }, { status: 500 });
}
}Why this job needs a monitor
Vercel documents cron delivery as best effort. A scheduled run can occasionally fail to reach the function, and no log is created when that happens. Vercel does not retry a failed invocation. A run that does not ping is how you find out.
Vercel can also invoke the same scheduled run more than once, so keep the job itself safe to repeat.
4. Check the first ping
Run the job from the project's Cron Jobs settings, or call the route with the CRON_SECRET header. The monitor turns from new to up.