Cron Jobs allow you to schedule tasks at specific intervals. Since the Vercel platform is event-driven, therefore not maintaining a running server, we recommend using a third-party service to schedule these tasks.
For example, let's say you want to hit a Serverless Function every 15 minutes. You can use any of the providers below to periodically hit your endpoint. If you need to execute a long job (greater than 30 seconds), you might consider breaking down the function into smaller pieces and using a queue (e.g. AWS SQS). This will allow you to track the state of the background job and potentially parallelize your task.
Depending on the frequency of your cron job, you might want to use different providers:
For low-frequency cron jobs (triggered once a day), a provider like GitHub Actions is a great fit, especially if you're already using GitHub as your code repository.
Define a new workflow file .github/workflows/cron.yaml
at the root of your repository to run a cron once every day.
name: daily-cron
on:
schedule:
- cron: '0 1 * * *'
jobs:
cron:
runs-on: ubuntu-latest
steps:
- name: Call our API route
run: |
curl --request POST \
--url 'https://yoursite.com/api/cron' \
--header 'Authorization: Bearer ${{ secrets.API_SECRET_KEY }}'
An example GitHub Actions workflow for a cron job.
This Cron Job forwards an API key to securely access your Serverless Function. For example:
import { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method === 'POST') {
try {
const { authorization } = req.headers;
if (authorization === `Bearer ${process.env.API_SECRET_KEY}`) {
res.status(200).json({ success: true });
} else {
res.status(401).json({ success: false });
}
} catch (err) {
res.status(500).json({ statusCode: 500, message: err.message });
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
An example Serverless Function with authorization.
You can verify this is working locally by running:
curl --request POST \
--url 'http://localhost:3000/api/cron' \
--header 'Authorization: Bearer API_SECRET_KEY'
Use cURL to test your Cron Job locally.
For high-frequency cron jobs (triggered every minute), a provider like Upstash's QStash is a better fit.
First, install the Upstash QStash library for Next.js:
npm i @upstash/qstash
Then, create the following endpoint in your application:
import { NextApiRequest, NextApiResponse } from 'next';
import { verifySignature } from '@upstash/qstash/nextjs';
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
try {
res.status(200).json({ success: true });
} catch (err) {
res.status(500).json({ statusCode: 500, message: err.message });
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
export default verifySignature(handler);
export const config = {
api: {
bodyParser: false,
},
};
Now, complete the following steps to configure your cron job on Upstash:
Upstash also offers retries – if your API endpoint does not respond with a success status code (2XX), it automatically retries the request to ensure every cron is completed successfully.
Here's a starter kit that shows how cron jobs work with Vercel Functions and Upstash: