In many projects, there is a need to automate the execution of functions or scripts at specific times. To address this need in Node.js, you can use the node-cron
library.
In this article, we’ll cover how to install the package, explore best practices, build a simple project, and deploy it to the cloud.
Cron is a task scheduler used in Unix-like operating systems (such as Linux) that allows you to automatically run commands or scripts on a schedule. The schedule is written in crontab format, where each line describes the time and command to be executed.
node-cron
is a library for Node.js that implements cron functionality directly in JavaScript applications. It allows you to create tasks that run on a given schedule in real-time in a selected time zone, just like classic cron in Unix systems.
Key Advantages of node-cron:
The syntax of node-cron
is similar to traditional cron:
Valid field values:
Field |
Values |
Seconds |
0–59 |
Minutes |
0–59 |
Hours |
0–23 |
Day of Month |
1–31 |
Month |
1–12 (or names) |
Day of Week |
0–7 (or names, 0 or 7 = Sun) |
Using Multiple Values
const cron = require('node-cron');
cron.schedule('1,2,4,5 * * * *', () => {
console.log('Runs at minute 1, 2, 4, and 5');
});
Using Ranges
const cron = require('node-cron');
cron.schedule('1-5 * * * *', () => {
console.log('Runs every minute from 1 to 5');
});
Using Step Values
Step values can be used with ranges or asterisks by adding /
and a number. Example: 1-10/2
is the same as 2, 4, 6, 8, 10
.
You can also use it after *
, e.g. */2
to run every 2 minutes.
const cron = require('node-cron');
cron.schedule('*/2 * * * *', () => {
console.log('Runs every 2 minutes');
});
Using Names for Months and Days
You can use full names for months and days of the week:
const cron = require('node-cron');
cron.schedule('* * * January,September Sunday', () => {
console.log('Runs on Sundays in January and September');
});
Or abbreviated names:
const cron = require('node-cron');
cron.schedule('* * * Jan,Sep Sun', () => {
console.log('Runs on Sundays in January and September');
});
The main method in node-cron
is schedule()
, which is used to set up a task.
It takes a cron expression, the task function, and an optional configuration object:
scheduled
: whether the task is started automatically (Boolean)timezone
: the time zone the cron will follow (String)Example:
const cron = require('node-cron');
cron.schedule('0 1 * * *', () => {
console.log('Will run at 01:00 Cyprus time');
}, {
scheduled: true,
timezone: "Europe/Cyprus"
});
You can manage the state of a scheduled task using:
start()
— starts a stopped taskstop()
— stops a running taskStarting a task:
const cron = require('node-cron');
const task = cron.schedule('* * * * *', () => {
console.log('Stopped task is now running');
}, {
scheduled: false
});
task.start();
Stopping a task:
const cron = require('node-cron');
const task = cron.schedule('* * * * *', () => {
console.log('Will run every minute until stopped');
});
task.stop();
Let’s set up our environment for working with Node.js and node-cron
.
To begin local development, you need to install a recent version of Node.js (we recommend v22.14.0 LTS). This will install npm (Node Package Manager).
For Windows:
For Linux / macOS:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
node -v && npm -v
Make sure the versions of Node.js and npm display correctly.
Create a new directory for your project and navigate into it:
mkdir node-cron-project && cd node-cron-project
Initialize the project:
npm init -y
Install node-cron
:
npm install --save node-cron
Let’s build a simple but interesting project using the node-cron
library. Our task is to automatically fetch the USD to EUR exchange rate and save the data to a file.
This project is simple, yet it effectively demonstrates how to use node-cron for scheduled tasks.
Install additional dependencies for the project:
npm install axios fs
axios
— for making HTTP requests (to fetch exchange rate data)fs
— built-in module to work with the file system (to write to files)Our app will do the following:
exchange_rates.txt
Create a file named index.js
and paste in the following code:
const cron = require('node-cron');
const axios = require('axios');
const fs = require('fs');
// Create file if it doesn't exist
if (!fs.existsSync('exchange_rates.txt')) {
fs.writeFileSync('exchange_rates.txt', '');
}
// Function to fetch exchange rate
async function getExchangeRate() {
try {
const response = await axios.get('https://open.er-api.com/v6/latest/USD');
const rate = response.data.rates.EUR;
return rate;
} catch (error) {
console.error('Error fetching exchange rate:', error);
return null;
}
}
// Function to save data to file
function saveData(rate) {
const currentTime = new Date().toLocaleString();
const data = { time: currentTime, rate };
fs.appendFileSync('exchange_rates.txt', `${JSON.stringify(data)}\n`);
console.log(`Rate saved: ${currentTime} - ${rate} EUR`);
}
// Cron job running every minute
cron.schedule('* * * * *', async () => {
const rate = await getExchangeRate();
if (rate !== null) {
saveData(rate);
}
});
console.log('Data collection started...');
Let’s explain what exactly this code does:
if (!fs.existsSync(...))
— Checks if the file exchange_rates.txt
exists; if not, it creates it.getExchangeRate()
— Fetches the USD to EUR exchange rate using a public API (in this case, open.er-api.com
).saveData()
— Saves the retrieved rate and current timestamp to the file.cron.schedule('* * * * *', ...)
— Sets up a cron job that runs every minute to get and save the latest exchange rate.To run your project, execute:
node index.js
You will see this message in the console:
Data collection started...
And a little later you’ll see logs like:
Rate saved: 4/9/2025, 12:00:00 PM - 0.92 EUR
And the exchange_rates.txt
file will contain entries with the date, time, and exchange rate.
Let’s apply node-cron
in a practical task. We’ll write a script that automatically sends emails. Companies often use this case to send various promotional content. It’s simple to implement but quite functional.
First, we need to obtain a token for your Gmail account:
First, install the required libraries. Since node-cron
is already installed, we only need to install nodemailer
:
npm install nodemailer
Now create a file called app.js and write the following code:
const nodemailer = require('nodemailer');
const cron = require('node-cron');
const recipients = [
'recipient1@gmail.com',
'recipient2@outlook.com'
];
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'sender@example.com',
pass: 'PASSWORD'
}
});
function sendEmail(recipient) {
let mailOptions = {
to: recipient,
subject: 'Scheduled Email',
text: 'This email was sent automatically on a schedule using node-cron.',
html: '<b>This email was sent automatically on a schedule using node-cron.</b>'
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(`Error sending email to ${recipient}:`, error);
} else {
console.log(`Email successfully sent to ${recipient}:`, info.response);
}
});
}
cron.schedule('* * * * *', () => {
console.log('Running cron job...');
recipients.forEach((recipient) => {
sendEmail(recipient);
});
});
Explanation:
recipients
array contains the list of email recipients.transporter
variable holds the authentication info for the sender. Replace user
with your Gmail address and pass
with the generated app password.sendEmail()
is a function that takes a recipient's address and sends an email. mailOptions
holds the subject, plain text, and HTML content. cron.schedule('* * * * *')
task runs every minute, calling sendEmail()
for each recipient.To run the file, use the command:
node app.js
After a couple of minutes, you’ll see output in the console confirming the emails have been sent. Check your inbox, and you should see the emails arriving.
After development, we’ll deploy the app to the cloud. For this lightweight mailer, a minimal server setup is sufficient.
1. Install Node.js on your server:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
Check the installation:
node -v && npm -v
2. Create the project directory:
cd /home && mkdir nodemailer
3. Upload your files (app.js and package.json)
rsync -av --exclude="node_modules" ./ root@166.1.227.189:/home/nodemailer
Explanation:
--exclude="node_modules"
— skip uploading installed libraries./
— source directoryroot@166.1.227.189:/home/nodemailer
— target path on the server4. SSH into the server and verify the files:
cd /home/nodemailer && ls
5. Install dependencies:
npm install
6. Run the script:
node app.js
Check if the emails are being sent correctly. If there’s an issue, make sure port 465 (SMTP) is open on the server. If not, contact support to open it.
To keep the app running even after closing the terminal, create a systemd
unit file:
sudo nano /etc/systemd/system/nodemailer.service
Paste the following content:
[Unit]
Description=NodeMailer Service
After=network.target
[Service]
User=root
WorkingDirectory=/home/nodemailer
ExecStart=/root/.nvm/versions/node/v22.14.0/bin/node /home/nodemailer/app.js
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Note: Adjust WorkingDirectory
and ExecStart
paths if necessary.
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable nodemailer.service
sudo systemctl start nodemailer.service
Check status and logs:
sudo systemctl status nodemailer.service
sudo journalctl -u nodemailer.service -f
You should see active (running) if everything is working properly.
Restart the service:
sudo systemctl restart nodemailer.service
Stop the service:
sudo systemctl stop nodemailer.service
Delete the service:
sudo systemctl disable nodemailer.service
sudo rm /etc/systemd/system/nodemailer.service
sudo systemctl daemon-reload
The node-cron
library is a powerful tool for automating tasks on the Node.js platform.
In this article, we created a simple app that retrieves USD to EUR exchange rates and writes them to a file, and we also explored a real-world use case: automatically sending scheduled emails.
We’ve seen how easily node-cron
enables you to schedule recurring jobs, from data collection to user interactions. It’s a great choice for developers looking for a reliable and user-friendly scheduling system in Node.js projects.
Its flexibility and ease of use make node-cron
an essential tool in any modern backend developer’s toolkit.