Cron Jobs

Scheduling Cron Jobs in Node.js

By: August Flanagan|Last Updated: Oct 09, 2026

JavaScript is one of the most widely used programming languages, and GitHub's 2022 Octoverse ranked it first on the platform ¹, so it is no surprise that people write cron jobs in it.

In this guide you’ll learn how to run any Node.js script as a cron job. We also explore other ways to add cron-like functionality to Node.js apps while avoiding some of the pitfalls of traditional cron jobs.

What is a cron job?

Traditionally, cron jobs are user-defined scripts/commands that are executed on a repeating schedule by the Unix cron scheduler. Now used by many background task systems, the term broadly means a piece of code running in the background at a scheduled time.

What the * * * * * ?!?

One of the strangest parts of a cron job is the scheduling syntax, e.g.  */3 2 * * 0-3.

Reminiscent of regular expressions, it is very hard to remember. See our guide on cron schedule syntax or use crontab.guru to translate a cron expression to english.

Run a Nodejs script as a cron job

Any Node script can be executed from the command line as:

node /path/to/script.js

Thus, the first step to running your Node script as a cron job is to manually execute your script from the command line of your server, and to verify that it does what you expect.

Note: Even if your script executes as expected, it's still possible for it to fail when executed by cron. We'll cover this in detail below.

Once you've successfully tested your script, it's time to configure it to be run by the cron scheduler.

There are five different ways to schedule cron jobs, but we will cover the two most common options.

  • Scheduling a cron job when you have root or sudo privileges

    With administrator-level access to a linux instance, a best practice is to create an application-specific crontab file in the server's cron.d directory, usually located at /etc/cron.d/. This directory is scanned every minute by cron, and all you need to do is copy a crontab file into place. Below is an example single line crontab file.

    # Run the daily_analytics.js script once a day as the deploy user.
    # Files in /etc/cron.d/ need the username. A user crontab does not.
    0 0 * * * deploy node /etc/scripts/daily_analytics.js
    
  • Scheduling a cron job without root privileges

    Cron jobs can also be scheduled in a user crontab file. These user crontabs can only run commands as the user they are assigned to.

    To edit your user crontab, use the crontab -e command:

    $ crontab -e
    

    From the text editor, add your new cron entry:

    # m h dom mon dow   command
    0 0 * * * node /path/to/script.js
    

Common Mistakes

With your script written, tested and scheduled you are almost done. You would think that a script that works for you will also work when run as a cron job, but there are a few key differences between your shell and the cron execution environment and these differences can often cause headaches when scheduling jobs:

  1. Incorrect file permissions or ownership

    The cron daemon will be executing your script as a specific user, and your Node.js must be executable by that user. You can check the file permissions of your script with:

    ls -l /path/to/script.js
    
  2. Not using absolute paths

    The current working directory used by Cron depends on several factors, but it's usually the job owner's home directory. Avoid any confusion here by exclusively using fully-qualified paths when you add the job to the crontab file. Similarly, if your script is invoking any other commands, it should use a fully qualified path or set its own working directory before doing any invocations.

  3. Missing environment variables

    Even though cron runs your cron jobs using a real user account, it does not trigger an interactive session, so any environment variables you may be loading in .bash_profile or .bashrc will not be available. If your script expects certain environment variables, you can either set them within the crontab file itself, or have each line of your crontab source your .bash_profile before invoking your script.

    0 0 * * * source ~/.bash_profile ; node /etc/scripts/daily_analytics.js
    

This is by no means a comprehensive list of possible errors. If you're still stuck, our troubleshooting guide walks through the reasons that cause most cron job failures.

Run cron jobs with Node-Cron

One of the interesting language features of Node.js is the event loop, which makes it practical to run a cron-like scheduler inside the process.

That makes it easy to write "cron jobs" from within your Node.js application, so the code can be colocated and version controlled. And, of course, it means not having to SSH onto a server in order to update a crontab file, or otherwise figure out how to deploy crontab updates.

Node-Cron is one popular library for running cron jobs directly from within your Node.js application, and it uses the ever-present cron syntax like so:

var cron = require('node-cron');

cron.schedule('1,2,4,5 * * * *', () => {
  console.log('running every minute 1, 2, 4 and 5');
});

It is very popular to use Node-Cron with Express, and Digital Ocean has written an excellent tutorial on getting started.

Run cron jobs with Vercel

Vercel has become one of the most popular platforms for deploying modern Javascript applications, and in early 2023 they announced built-in support for cron jobs.

With Vercel's take on "cron jobs" you provide a cron schedule syntax and the path to an API endpoint, and Vercel will handle calling this endpoint on your defined schedule. Put this in vercel.json:

{
  "crons": [
    {
      "path": "/api/cron",
      "schedule": "0 5 * * *"
    }
  ]
}

This is a light-weight alternative to traditional cron jobs, with a real limit: the work has to finish inside the HTTP request, so a long job is a poor fit.

If you are not using Vercel, but would like to use the same cloud scheduler concept, there are a number of alternatives, including Cron-Job.org or Google's Cloud Scheduler.

Monitor Node.js cron jobs

Because cron jobs are "background jobs", it's important to monitor them, otherwise you will eventually discover a job has been failing silently for far too long. Depending on the job, this can have major impacts on operations and performance.

Cronitor's JavaScript SDK monitors Node.js cron jobs. Set CRONITOR_API_KEY to an SDK Integration key from Settings → API before the process starts, then call require('cronitor')() with no argument. The constructor still accepts a key string if you pass one. Do not commit the key. The package runs on servers, not in the browser.

Monitoring Node.js Cron Jobs

const cronitor = require('cronitor')();

let importantAsyncWorker = cronitor.wrap('important-worker', async function() {
    // do some async work
});

// cronitor will track the start and end time and state (promise resolved or rejected).
await importantAsyncWorker();

Monitoring Node-Cron Jobs

const cronitor = require('cronitor')();
const nodeCron = require('node-cron');

cronitor.wraps(nodeCron);

// the first parameter is now the key that Cronitor will use
// to send telemetry events when the jobs runs, completes or fails
cronitor.schedule('SendWelcomeEmail', '*/5 * * * *', function() {
    console.log('Sending welcome email to new sign ups every five minutes.');
});

cronitor.wraps is the same helper the SDK docs point at for node-cron and the cron package. The full options are in the package readme.

Previous
PHP Cron Jobs