In many apps, users expect notifications exactly when they need them—like Google Meet reminders. In our Node.js app, we faced the challenge of sending dynamic, user-specific reminders at the precise times chosen by users.
At first, we considered running a cron job every few minutes to check for due reminders. But this approach quickly became inefficient and unscalable: it constantly queried the database, caused delays, and struggled to handle a growing number of users.
After some research, we found the perfect solution: node-schedule combined with luxon. This approach allows us to schedule reminders dynamically, handle timezones, and efficiently manage one-time or repeating notifications.
Scheduling a Reminder
We create a scheduled job for each reminder using node-schedule, converting user-selected times to the correct timezone with luxon:
import schedule, { Job } from "node-schedule";
import { DateTime } from "luxon";
class ReminderScheduler {
private jobs: Map<string, Job> = new Map();
scheduleReminder(reminder) {
const reminderDate = DateTime.fromJSDate(reminder.reminderDate)
.setZone("Europe/Dublin")
.toJSDate();
this.cancelReminder(reminder._id.toString());
const job = schedule.scheduleJob(reminder._id.toString(), reminderDate, async () => {
console.log(`Reminder triggered: ${reminder.name}`);
await this.handlePostTriggerUpdate(reminder);
});
this.jobs.set(reminder._id.toString(), job);
console.log(`Scheduled reminder ${reminder._id} at ${reminderDate.toISOString()}`);
}
Post-Trigger Update
After a reminder is triggered, we update its status. If the reminder repeats daily or weekly, we automatically schedule the next occurrence:
private async handlePostTriggerUpdate(reminder) {
if (!reminder.isOneTimeReminder) {
const next = DateTime.fromJSDate(reminder.reminderDate)
.plus({ days: reminder.repeatDuration === "Daily" ? 1 : 7 });
reminder.reminderDate = next.toJSDate();
this.scheduleReminder(reminder);
} else {
reminder.isActive = false;
}
console.log(`Post-trigger update done for ${reminder._id}`);
}
**Canceling a Reminder
**
We also allow reminders to be canceled or rescheduled easily:
cancelReminder(reminderId: string) {
const job = this.jobs.get(reminderId);
if (job) {
job.cancel();
this.jobs.delete(reminderId);
console.log(`Canceled reminder job ${reminderId}`);
}
}
}
Why This Approach Works
-
Users receive notifications exactly when they want them, without inefficient polling.
-
Supports timezones with Luxon.
-
Handles one-time, daily, and weekly reminders reliably.
-
Scalable and maintainable for a growing user base.
Summary
Using node-schedule with luxon allows your Node.js app to provide dynamic, personalized reminders that are reliable and efficient. It’s a simple yet powerful way to implement real-time notifications for any app.