How to Set Up Cron Jobs in Node.js (Complete Guide)
Learn how to schedule cron jobs in Node.js using node-cron and other libraries. Includes code examples, error handling, PM2 setup, and production tips.
Prerequisites
- Node.js 18+
- npm or yarn
- Basic understanding of cron syntax
In this guide
Cron Jobs in Node.js
Unlike system cron, Node.js cron jobs run inside your application process. This means they have access to your app's context — database connections, environment variables, and modules — without spawning separate processes.
The most popular library is node-cron, which provides a simple API for scheduling tasks using standard cron expressions.
Quick Start with node-cron
Install node-cron:
npm install node-cronSchedule a task:
import cron from 'node-cron';
cron.schedule('*/5 * * * *', () => {
console.log('Running task every 5 minutes');
});
cron.schedule('0 9 * * *', () => {
console.log('Good morning! Running daily task.');
});That's it. The tasks run as long as your Node.js process is alive.
node-cron API Deep Dive
Scheduling with options:
const task = cron.schedule('0 * * * *', () => {
console.log('Hourly task');
}, {
scheduled: false,
timezone: 'America/New_York',
});
task.start();
task.stop();Validating expressions:
cron.validate('*/5 * * * *'); // true
cron.validate('invalid'); // falseUsing seconds (6-field expressions):
// Run every 30 seconds
cron.schedule('*/30 * * * * *', () => {
console.log('Every 30 seconds');
});Alternative: The cron Package
The cron package offers a class-based API with more control:
npm install cronimport { CronJob } from 'cron';
const job = new CronJob(
'0 */2 * * *',
function () {
console.log('Running job');
},
null,
true,
'America/Los_Angeles'
);
job.stop();
job.start();
console.log(job.nextDate());The cron package uses Luxon for date handling since v2.
Common Cron Expressions
Expressions you'll use most often:
* * * * *— Every minute*/5 * * * *— Every 5 minutes0 * * * *— Every hour0 0 * * *— Daily at midnight0 9 * * 1-5— Weekdays at 9 AM0 0 1 * *— First day of every month0 0 * * 0— Every Sunday at midnight
Every weekday at 9:00 AM
Next runs (UTC):
Mon, May 18, 2026 09:00
Tue, May 19, 2026 09:00
Wed, May 20, 2026 09:00
Error Handling & Logging
Always wrap your cron callbacks in try/catch. An uncaught exception can crash your process:
cron.schedule('0 * * * *', async () => {
try {
await processData();
console.log('[cron] processData completed');
} catch (error) {
console.error('[cron] processData failed:', error);
}
});Preventing overlapping runs:
let isRunning = false;
cron.schedule('*/5 * * * *', async () => {
if (isRunning) return;
isRunning = true;
try {
await longRunningTask();
} finally {
isRunning = false;
}
});Production: PM2 and systemd
In production, you need your Node.js process to stay alive:
PM2 (recommended):
npm install -g pm2
pm2 start app.js --name "my-app"
pm2 save
pm2 startupsystemd service:
[Unit]
Description=My Node App
After=network.target
[Service]
Type=simple
User=node
WorkingDirectory=/opt/my-app
ExecStart=/usr/bin/node app.js
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.targetImportant: Node.js cron jobs run in-process. If your process restarts, any in-flight task is killed. For critical jobs, consider BullMQ or Agenda for database-backed scheduling.
Testing Cron Jobs
Separate your schedule from your task logic:
// tasks/cleanup.js
export async function cleanup() {
const deleted = await db.deleteOldRecords(30);
return { deleted };
}// cron.js
import cron from 'node-cron';
import { cleanup } from './tasks/cleanup.js';
cron.schedule('0 2 * * *', cleanup);// tasks/cleanup.test.js
test('cleanup deletes old records', async () => {
const result = await cleanup();
expect(result.deleted).toBeGreaterThanOrEqual(0);
});