Skip to content

How to Setup Cron Jobs on Vercel

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.

.github/workflows/cron.yaml
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:

pages/api/cron.js
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:

terminal
curl --request POST \
     --url 'http://localhost:3000/api/cron' \
     --header 'Authorization: Bearer API_SECRET_KEY'

Use cURL to test your Cron Job locally.

Note: GitHub Actions has a minimum time period of 5 minutes, which may not be reliable for higher frequency usage. For more reliable & high frequency cron jobs, we recommend the approach in the following section instead.

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:

terminal
npm i @upstash/qstash

Then, create the following endpoint in your application:

pages/api/cron.ts
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:

  1. Go to console.upstash.com/qstash and create a new account.
  2. Scroll down to the Request Builder and configure the endpoint URL as https://yoursite.com/api/cron.
  3. Select the type as "Scheduled".
  4. Configure the cron schedule as * * * * * (select the "day" dropdown and change it to "minute").
  5. Click "Schedule".

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:

Couldn't find the guide you need?