How to Build a Cron Job in Node.js

Cover Image for How to Build a Cron Job in Node.js
Wellerson
Wellerson

TL;DR

In this tutorial, we'll build a simple alarm clock that runs every day at 7 AM using Node.js. A cron job allows you to schedule tasks to run automatically at specific times or intervals.

We'll use the cron package to handle the scheduling. Cron jobs use a specific syntax to define when they should run—if you're new to this, crontab.guru is an excellent resource for learning and testing cron expressions.

Prerequisites: Basic knowledge of Node.js and Express is required, as we'll be setting up a simple server.

Installing Dependencies

 yarn add express

 yarn add cron

Project Setup

Since cron jobs run on the backend, we need a Node.js server. I'm using Express in this example, but you could also use Koa or any other framework. To make things easier, I've created a repository on GitHub with the complete code.

Let's start by looking at our main app.js file, where we'll import and initialize our cron job:


// app.js

import 'dotenv/config'
import './app/models'

import express from 'express'
import 'express-async-errors'
import cors from 'cors'

import { routes } from './routes'

import jobs from './app/jobs'

import { keys } from './configs/keys'

const port = keys.port || 3001

const app = express()

app.use(cors())
app.use(express.json({}))
app.use(express.urlencoded({ extended: true }))
app.use(routes)

// Jobs
jobs.clock()

app.listen(port, () => {
  console.log(`We are live on ${port}`)
  console.log(`Environment: ${keys.environment}`)
})

Notice the jobs.clock() call—this initializes our alarm clock cron job when the server starts. Let's dive into how this works.

Understanding the Cron Job Structure

The cron job logic lives in the jobs/clock folder. The main index.js file orchestrates everything by importing and configuring the necessary components:


import { CronJob } from 'cron'
import moment from 'moment'

import getCronTime from './getCronTime'
import { getJob } from './getJob'
import cronJobCompleted from './cronJobCompleted'
import cronJobShouldStart from './cronJobShouldStart'
import getTimeZone from './getTimeZone' 

function clock(): void {
  const job = new CronJob(
    getCronTime(),
    getJob,
    cronJobCompleted,
    cronJobShouldStart(),
    getTimeZone()
  )

  const nextDate = job.nextDate().format('DD/MM/YYYY HH:mm:ss')
  const appStartedAt = moment().format('DD/MM/YYYY HH:mm:ss')

  const loggerPrefix = '[CRON JOB] clock job'
  
  console.log(`${loggerPrefix} next date: ${nextDate}`)
  console.log(`${loggerPrefix} started at: ${appStartedAt}`)
}

export { clock }

We're importing two external libraries: cron for scheduling and moment for date formatting. The remaining imports are helper functions we'll create. Let's go through each one.

getCronTime

This function defines when the cron job should run:


function getCronTime(): string {
  return '0 7 * * *'
}

export default getCronTime

The cron expression 0 7 * * * means "run at minute 0 of hour 7, every day." You can use crontab.guru to build and test your own expressions.

getJob

This is the function that executes when the scheduled time arrives. For our alarm clock example, it simply logs a message:


const getJob = (): void => {
  console.log('ALARM CLOCK RINGING!!!')
}

export { getJob }

While this example is simple, you can do anything here—send emails, generate reports, clean up databases, sync data with external APIs, and more.

cronJobCompleted

This callback runs after the cron job completes. We're returning null since we don't need any post-execution logic:


function cronJobCompleted(): null {
  return null
}

export default cronJobCompleted

cronJobShouldStart

This determines whether the cron job should start automatically. By returning true, the job begins as soon as it's created. If you return false, you'll need to manually call .start() on the job instance:


function cronJobShouldStart(): boolean {
  return true
}

export default cronJobShouldStart

getTimeZone

This sets the timezone for the cron schedule. I'm using São Paulo's timezone, but you should adjust this to match your needs:


function getTimeZone(): string {
  return 'America/Sao_Paulo'
}

export default getTimeZone

Logging and Debugging

To help with debugging and monitoring, the clock function includes logging that shows when the job started and when it will run next:


const nextDate = job.nextDate().format('DD/MM/YYYY HH:mm:ss')
const appStartedAt = moment().format('DD/MM/YYYY HH:mm:ss')

const loggerPrefix = '[CRON JOB] clock job'

console.log(`${loggerPrefix} next date: ${nextDate}`)
console.log(`${loggerPrefix} started at: ${appStartedAt}`)

This is helpful for verifying that your cron job is configured correctly and knowing exactly when it will execute next.

Conclusion

That's it! You now have a working cron job in Node.js. This modular structure makes it easy to add more scheduled tasks—just create a new folder with the same pattern and call it from your main app file.

Cron jobs are incredibly useful for automating repetitive tasks like sending scheduled emails, generating reports, cleaning up old data, or syncing with external services. Feel free to check out the complete code on GitHub and adapt it to your needs.