How to Schedule Daily Emails with Node Cron
8/25/2025
James Oluwaleye
Learn how to schedule automated tasks in Node.js using Node Cron. This step-by-step guide covers setup, cron expressions, sending emails, best practices, and deploying your project to run 24/7.

How to Schedule Daily Emails with Node Cron
- 1.What We’ll Use
- 2.Set Up the Project
- 3.Install Dependencies
- 4.Create the Mailer Function
- 5.Schedule the Task with Node Cron
- 6.Understanding Cron Expressions
- 7.Run the App
- 8.Best Practices
- 9.Keeping It Running 24/7
- 10.Wrapping Up
Automation is essential for many of today’s applications. Think about things like reminders, notifications, cleaning up databases, or backing up files. These tasks need to happen regularly at certain times, and doing them by hand is neither enjoyable nor dependable. That’s where cron jobs come into play.
In this guide, we’ll create a simple Node.js app that sends an email automatically every day at 8 AM using two tools: Node Cron for scheduling the tasks, and Nodemailer for sending the emails.
What We’ll Use
Before we start coding, let’s learn about the tools we’ll be using.
- Node.js: This is a JavaScript runtime that allows us to create server-side applications, which is great for tasks that need to run in the background, like scheduling jobs.
- Node Cron: This is a library for Node.js that works like traditional Linux cron jobs. It lets us set up a schedule based on time using simple commands.
- Nodemailer: This is a popular package that helps send emails from Node.js using an SMTP server.
By using these three tools together, we can set up a system that sends emails at specific times without needing any manual effort.
Set Up the Project
Every Node.js project starts with a folder and a package file. This first step makes sure we have the right structure for installing and running our dependencies. Open your terminal and create a new folder:
The command npm init -y
creates a package.json
file with default settings, where npm keeps track of our dependencies and scripts. Now, you have an empty project ready for coding.
Install Dependencies
To make our project work, we need two external libraries:
- node-cron: This handles scheduling.
- nodemailer: This sends emails.
Run this command in your terminal:
This will download the libraries into your project and list them in package.json. Without these, we would have to manage timing and email sending ourselves, which can be complicated and lead to errors.
Create the Mailer Function
Now that our libraries are installed, let’s focus on the part that sends the email. We’ll keep this in a file named mailer.js
.
Here nodemailer.createTransport
sets up a “mail transporter,” which is like setting up your email app with the server, port, and login info then sendMail
creates and sends an email with a subject, message, and recipient. We use a try/catch block to handle any errors so they don’t break the app. At this point, if you call sendMail()
manually, you should be able to send an email.
Schedule the Task with Node Cron
Now that our email function is ready, it’s time to schedule when it runs. This will be done in our main file, index.js.
cron.schedule takes a cron expression (for timing) and a callback (the job). Our expression "0 8 * * *"
means: run at 8:00 AM every day. The job calls sendMail()
, which triggers the email. This is where the automation happens, Node Cron takes care of the timing for you.
Understanding Cron Expressions
Cron expressions might look confusing, but they are just a series of numbers separated by spaces. Each position represents a time unit:
Here are some examples:
* * * *
→ Runs every minute0 9 * * *
→ Runs at 9 AM every day0 */2 * * *
→ Runs every 2 hours0 0 * * 0
→ Runs every Sunday at midnight
During development, it’s common to use * * * * *
so you can test your job without waiting for hours.
Run the App
Now let’s see everything in action. Start your app with this command:
If everything is set up correctly, you’ll see:
At the scheduled time (or every minute if you used * * * * *
), the script will run, and you should receive an email. This is the moment when theory becomes practical, your app is now working automatically without you having to do anything
Best Practices
Setting up a cron job is easy, but making sure it works well, is secure, and can grow with your needs takes a little more thought. Many developers face problems where jobs stop working without warning, run more than once, or fail after being launched. To avoid these issues, here are some best practices to follow:
Use App Passwords for Email Accounts
Most email services, such as Gmail, Zoho, and Outlook, have increased their security. Trying to log in with your regular email password from an app might not work, and it could even get your account locked. Instead, use App Passwords, which are special codes you can create in your email settings. These passwords are made specifically for third-party apps like Nodemailer, keeping your main password safe.
For example, if you’re using Gmail, turn on two-factor authentication (2FA) and then create a 16-character app password. Use this app password in your settings instead of your regular password.
Add Detailed Logging
Cron jobs run in the background, and you often can’t see what’s happening. Without logging, you might not know if your job ran, failed, or completed successfully. Always log:
- When a job starts
- When it finishes successfully
- When it fails (including error details)
For larger projects, consider using a logging library like Winston or send logs to a monitoring tool. This way, you'll be able to track when jobs ran and how well they worked.
Handle Errors Gracefully
Don’t assume your job will always work perfectly. Emails might fail due to a bad connection, expired login details, or a temporary block from your email provider. Wrap your cron job code in a try/catch block and log any errors. You can also set up alerts (like sending an email to yourself if it fails or logging errors to a service like Sentry) so that you know right away when something goes wrong.
This way, one failure won’t crash your entire app or happen without you noticing.
Watch Out for Scaling Issues
Cron jobs work great on a single server. But if you deploy your app on several servers (to handle more users), each server will try to run the job at the same time. This could mean sending the same email multiple times.
To fix this, you can:
- Use a dedicated worker: Run the cron jobs on just one server.
- Job queues: Use tools like Bull (with Redis) to manage jobs so that only one worker handles them.
- External schedulers: Services like AWS CloudWatch, Google Cloud Scheduler, or Quartz can make sure jobs run only once, no matter how many servers you have.
By thinking about scaling early, you can prevent messy duplicates later.
Keeping It Running 24/7
When you run the script on your laptop during development, everything works fine. But if you close your terminal or turn off your computer, the cron job will stop. That’s why, for production use, you need to host your script on a server that runs all the time.
Here are some options:
Free Hosting Platforms
Services like Render and Railway make it simple to deploy Node.js apps without worrying about the technical details. These platforms keep your app running and ensure your cron jobs continue to work daily. They’re great for small projects or side applications.
(Note: Heroku was once the popular free platform, but it’s no longer free.)
VPS Providers
If you want more control, you can use a VPS (Virtual Private Server) like DigitalOcean, Linode, or AWS Lightsail. This gives you a full server to run your Node.js app and tools like PM2 (a process manager that keeps your app running even after crashes or reboots).
With a VPS, you manage updates, scaling, and monitoring, which gives you flexibility but requires more setup.
Cloud Functions and Managed Schedulers
If you don’t want to run a server at all, cloud providers offer serverless options. For example:
- AWS Lambda + CloudWatch Events
- Google Cloud Functions + Cloud Scheduler
- Azure Functions + Timer Triggers
These let you run small pieces of code on a schedule without managing a server. They’re cost-effective and automatically handle scaling. Cron jobs are only useful if they actually run when you expect them to. Deploying your app ensures that even when you’re asleep, traveling, or offline, your jobs will still run at the right times.
Wrapping Up
We’ve gone through how to build a working Node.js project that sends an email every day at 8 AM using Node Cron and Nodemailer. Along the way, we talked about:
- Setting up a Node.js project
- Installing and using Node Cron
- Writing cron expressions to control schedules
- Sending emails with Nodemailer
- Testing locally
- Best practices for reliability and scaling
- How to deploy and keep it running 24/7
This approach is simple but very powerful. You can start small like sending yourself reminders and then grow it to handle daily reports, database cleanups, or even important business notifications. A great next step would be to expand this project into something more advanced, like scheduling a weekly report with a PDF attachment or running multiple cron jobs for different tasks. This way, you’ll move from just one automated email to a fully automated workflow.