How to add cron jobs on Vercel
Configure Vercel cron jobs in <code>vercel.json</code> with a <code>crons</code> array specifying <code>path</code> and <code>schedule</code> cron expression, create a matching API route endpoint, deploy to production, and monitor in the dashboard. Free tier limits to 1-2 jobs with daily frequency; use Pro for more. Design handlers as idempotent and secure with <code>CRON_SECRET</code>.
Prerequisites
- Vercel account and project linked to Git
- Serverless or Edge Function API route knowledge
- Basic cron expression syntax
- Familiarity with Vercel deployments
- Node.js or TypeScript for handlers
Step-by-Step Instructions
Create Serverless or Edge Function endpoint
api/cron.ts or app/api/cron/route.ts in Next.js. This handles cron invocations via HTTP GET. Example for Node.js: import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
// Your task logic here (make idempotent for duplicates)
res.status(200).json({ success: true });
} Path must start with /; test locally with curl http://localhost:3000/api/cron.Secure the cron endpoint
CRON_SECRET (random 16+ chars) in Vercel dashboard. Check Authorization header in handler: const authHeader = req.headers.authorization;
if (!process.env.CRON_SECRET || authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return res.status(401).json({ success: false });
}
// Proceed with task Vercel auto-sends it as Bearer token on invocation.Configure vercel.json at project root
vercel.json with crons array. Each job needs path (starts with /, e.g. "/api/cron") and schedule (5-field cron string, UTC). Example for daily 5 AM: {
"crons": [
{
"path": "/api/cron",
"schedule": "0 5 * * *"
}
]
} Examples: every 24h "0 0 * * *", hourly "0 * * * *".Deploy to production
main) for auto-deploy, or use CLI vercel --prod. Crons activate only on production deployments (previews ignored). Invocations hit your prod URL like https://your-project.vercel.app/api/cron. Post-build, jobs are live.Verify in Vercel Dashboard
requestPath:/api/cron.Monitor and test locally
curl http://localhost:3000/api/cron (prod skips redirects). Dashboard shows invocations, errors. Jobs non-concurrent by default; duration matches Function limits.Update or disable crons
vercel.json (change schedule/path or remove), redeploy. Or use dashboard Disable Cron Jobs button (re-enable via redeploy). Changes reflect post-deploy.Handle concurrency and idempotency
Common Issues & Troubleshooting
Cron not triggering or no dashboard entry
Ensure production deployment (previews ignored); redeploy via Git push to main or <code>vercel --prod</code>. Check Cron Jobs tab.
Build fails with invalid config
Validate <code>vercel.json</code> JSON and cron syntax (5 fields, path starts with <code>/</code>). Hobby: once/day max.
401 Unauthorized on invocation
Set <code>CRON_SECRET</code> env var and verify <code>Authorization: Bearer ${process.env.CRON_SECRET}</code> in handler.
Timeouts or cold starts
Optimize handler; add <code>?__no_cache=1</code> query if cached. Upgrade to Pro for better reliability.
Frequent jobs fail on Hobby
Free/Hobby limits 1-2 jobs, daily only. Upgrade to Pro for up to 40 jobs, any frequency.