DevOps & Cloud
How to Setup Vercel Cron Jobs (and the Hobby Plan Workaround)
Vercel cron jobs are easy to configure on Pro plans, but Hobby users need a workaround. Here is how to handle background tasks on either plan.
By Tushar Gautam · · 6 min read
Short answer
Vercel cron jobs are configured via vercel.json for Pro and Enterprise users. If you are on the Vercel Hobby plan, which is restricted to once-daily executions, the best workaround is to expose a protected API route and trigger it externally using services like cron-job.org for granular scheduling.
Key takeaways
- Vercel Pro plans support cron syntax directly in the vercel.json configuration file.
- Hobby plan cron jobs are strictly limited to one execution per day per project.
- Using an external scheduler like cron-job.org allows you to run tasks as frequently as every minute on the Hobby plan.
- Always secure your cron endpoints with a secret token in the Authorization header to prevent unauthorized access.
- Background jobs are subject to Vercel's serverless function execution limits; keep tasks short or move them to a VPS.
Understanding Vercel Cron Limitations
Vercel offers built-in support for cron jobs, but the feature set depends heavily on your plan. If you are on a Pro or Enterprise plan, you can define schedules directly within your project configuration. This integration ensures that your tasks are managed by Vercel's infrastructure, which handles the execution triggers according to your defined schedule.
The Hobby plan is significantly more restrictive. While it does support cron jobs, you are limited to exactly one execution per 24-hour window. This limitation occurs because the platform manages resources based on the subscription tier, and free-tier infrastructure is shared and strictly metered. Consequently, if your application requires frequent data synchronization, hourly cleanup tasks, or low-latency monitoring, the standard Hobby configuration will not suffice.
To work around this, many developers (myself included) keep the logic inside a standard API route and use an external ping service. This avoids the cost of upgrading while maintaining the flexibility of custom intervals. By separating the trigger mechanism from the Vercel-native scheduler, you essentially treat your serverless endpoint as a generic webhook receiver, which is a common pattern for distributed systems that require external orchestration.
How to Configure Vercel Pro Cron Jobs
If you have a Pro subscription, you can define your schedule in the vercel.json file at the root of your project. Vercel uses standard cron syntax to manage execution timing, allowing you to define jobs with specific granularities ranging from minute-based intervals to daily or monthly tasks.
Each path specified in the cron array will be triggered as a GET request to your serverless function. Because these functions run in a stateless container environment, ensure these routes are idempotent. Idempotency is critical because serverless environments can occasionally retry failed invocations due to networking hiccups or transient infrastructure issues. If your job performs database updates, check whether the specific record has already been modified before executing the logic again to avoid duplicate data entries or inconsistent states.
Configuration in vercel.json is evaluated during the deployment process. When you push your code, the Vercel build system reads the file and registers the cron jobs with the underlying orchestration layer. This means that if you update the schedule, you must perform a new deployment for the changes to take effect in the production environment.
{
"crons": [
{
"path": "/api/cron/cleanup",
"schedule": "0 0 * * *"
}
]
}The Hobby Plan Workaround: External Schedulers
When you are on the Hobby plan, you cannot use the native cron configuration to run jobs more than once a day. Instead, you should create a standard Next.js API route that performs your task, ensuring that the route is structured to handle incoming HTTP requests just like any other endpoint in your application.
You can then use a service like cron-job.org to ping that specific URL at any interval you require. This transforms your serverless function into an externally triggered background worker. You configure the frequency within the external service's dashboard—for instance, setting a job to run every five minutes—and the service will send a GET request to your deployed API URL at that exact interval.
In your external scheduler, point the URL to your deployed API route. Because this request originates from the public internet, you must implement strict authentication to prevent malicious actors or automated bots from triggering your logic. If your endpoint is exposed without a guard, any entity that guesses or finds your URL will be able to consume your serverless execution minutes, which could lead to project suspension if you exceed usage quotas.
Securing Your Cron Endpoint
Exposing a URL for a cron job is dangerous if left public. If an attacker discovers your endpoint, they could trigger it repeatedly, incurring unnecessary execution time and potentially crashing your application or depleting your monthly function budget.
You should require a secret token in the request headers. Check for this token inside your API route before executing any business logic. Using the Authorization header is generally preferred over query parameters, as query parameters often end up in server access logs and browser history, whereas headers provide a more opaque way to pass sensitive credentials. By verifying this token against an environment variable stored in the Vercel dashboard, you ensure that only your designated scheduler has the permission to execute the code.
Here is a simple example of how to secure a route in a Next.js App Router API endpoint. This approach validates the incoming request before allowing the execution of downstream tasks, ensuring your system remains protected.
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const authHeader = request.headers.get('authorization');
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// Perform your logic here
return NextResponse.json({ success: true });
}When Should You Move to a VPS?
Vercel functions have strict execution duration limits. If your job takes longer than a few seconds or requires heavy memory, you will hit a timeout. While Vercel provides different limits based on your plan, these are intended for rapid request-response cycles rather than long-running background processing tasks.
While you can attempt to optimize your code by using streaming or batch processing, sometimes the serverless architecture itself is the problem. If you need to perform data scraping, complex file generation, or tasks requiring background processes like Celery and Redis, a VPS is a better fit. A VPS provides a persistent execution environment where you can maintain a running process or a worker pool that stays alive regardless of HTTP request constraints.
I use a VPS for tasks like managing RAG pipelines where scraping and vectorization might take several minutes, as this prevents the HTTP request-response cycle from timing out. By moving these tasks off Vercel, you gain full control over the runtime environment, allowing you to configure custom timeouts, install system-level dependencies, and manage persistent database connections that would otherwise be difficult to maintain in a serverless context.
| Feature | Vercel Pro Cron | Hobby + External Ping |
|---|---|---|
| Scheduling | Built-in (vercel.json) | External (cron-job.org) |
| Frequency | Configurable | Highly Flexible |
| Cost | Pro Subscription | Free |
| Setup Difficulty | Low | Moderate |
Gotchas and Common Pitfalls
The most common mistake is failing to handle cold starts. If your cron job runs rarely, the first execution might take significantly longer as Vercel spins up your function, potentially exceeding the timeout limit if your initialization logic is heavy. To mitigate this, keep your dependency footprint small and use lazy-loading for heavy libraries.
If you are using an external scheduler, ensure the timeout setting of the external service is high enough to accommodate your function's work. If the scheduler kills the connection before your function finishes, you might end up with partial executions, leaving your data in an indeterminate state. Check both the client-side timeout of the scheduler and the server-side timeout of your Vercel function to ensure they are aligned.
Lastly, keep your logs clean. In production, every ping from your external scheduler will show up in your Vercel logs. If you are polling every minute, these logs can accumulate rapidly, making it difficult to spot actual application errors among the sea of successful execution logs. Implementing a custom logger or filtering your log output can save hours of debugging time when something eventually goes wrong.
Frequently asked questions
Can I run cron jobs every minute on Vercel Hobby?
Not natively through Vercel's platform features, as the Hobby plan is restricted to one cron execution per 24 hours. You can achieve minute-by-minute execution by exposing an API route and hitting it from an external service like cron-job.org.
Why does my Vercel cron job time out?
Vercel serverless functions have a maximum execution duration (usually 10 to 60 seconds depending on your plan). If your job does not finish within this time, the execution is terminated. For long-running tasks, you should offload the work to a background worker on a VPS.
Is cron-job.org secure for my private endpoints?
It is secure as long as you implement a secret token mechanism. Never rely on the obscurity of the URL alone. By checking for a custom authorization header containing a secret value stored in your environment variables, you ensure only your scheduler can trigger the job.
Sources & further reading
About the author
Tushar Gautam is a full-stack & ai product engineer in India. He builds AI SaaS products such as an AI video ad generator, a RAG chatbot platform and a Razorpay-powered report service, mostly with Next.js, Flask and the Gemini API. See the projects, GitHub or LinkedIn.
This article was drafted with the help of AI (Google Gemini) from official documentation and published by Tushar Gautam. Spotted an error? Let me know.