Common Cron Job Use Cases in Node.js Cleanup, Notifications, and Reports
Learn the most common cron job use cases for Node.js applications data cleanup, email notifications, report generation, and database backups with code examples.
Common Cron Job Use Cases in Node.js
This guide covers the most practical cron job use cases for Node.js applications with code examples.
1. Data Cleanup Delete Old Sessions and Tokens
cron.schedule("0 0 * * *", async () => { console.log("Running daily cleanup..."); // Delete expired password reset tokens await User.updateMany( { resetPasswordExpires: { $lt: new Date() } }, { $unset: { resetPasswordToken: 1, resetPasswordExpires: 1 } } ); // Delete unverified users older than 30 days const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); await User.deleteMany({ isVerified: false, createdAt: { $lt: thirtyDaysAgo } }); // Delete old connection requests (rejected/ignored > 90 days) const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000); await ConnectionRequest.deleteMany({ status: { $in: ["rejected", "ignored"] }, updatedAt: { $lt: ninetyDaysAgo } }); console.log("Cleanup complete"); });
2. Email Notifications Daily Digest
cron.schedule("0 9 * * *", async () => { console.log("Sending daily digest..."); const users = await User.find({ emailBounced: false, emailComplained: false, "notificationPreferences.dailyDigest": true }); for (const user of users) { const pendingRequests = await ConnectionRequest.find({ toUserId: user._id, status: "interested", createdAt: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) } }).populate("fromUserId", "firstName lastName photoUrl"); if (pendingRequests.length > 0) { await sendEmail(user.email, "dailyDigest", { firstName: user.firstName, requests: pendingRequests }); } } console.log(`Digest sent to ${users.length} users`); });
3. Report Generation Weekly Analytics
cron.schedule("0 0 * * 1", async () => { console.log("Generating weekly report..."); const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); const stats = { newUsers: await User.countDocuments({ createdAt: { $gte: oneWeekAgo } }), totalUsers: await User.countDocuments(), newConnections: await ConnectionRequest.countDocuments({ status: "accepted", updatedAt: { $gte: oneWeekAgo } }), totalConnections: await ConnectionRequest.countDocuments({ status: "accepted" }), messagesSent: await Message.countDocuments({ createdAt: { $gte: oneWeekAgo } }) }; // Save report await WeeklyReport.create({ weekStarting: oneWeekAgo, weekEnding: new Date(), stats }); // Email to admins await sendEmail("[email protected]", "weeklyReport", stats); console.log("Weekly report generated:", stats); });
4. Database Backup
cron.schedule("0 2 * * *", async () => { console.log("Running daily backup at 2 AM..."); const { exec } = require("child_process"); const date = new Date().toISOString().split("T")[0]; const backupFile = `backup-${date}.archive`; exec(`mongodump --uri="${process.env.MONGODB_URI}" --archive=${backupFile} --gzip`, (error, stdout, stderr) => { if (error) { console.error("Backup failed:", error); return; } console.log("Backup completed:", backupFile); // Upload to S3 const s3 = require("../config/s3"); s3.upload({ Bucket: "devtinder-backups", Key: `backups/${backupFile}`, Body: fs.createReadStream(backupFile) }).promise(); } ); });
5. Subscription Renewal Reminders
cron.schedule("0 9 * * *", async () => { console.log("Checking subscription renewals..."); const threeDaysFromNow = new Date(Date.now() + 3 * 24 * 60 * 60 * 1000); const expiringSubscriptions = await Subscription.find({ status: "active", endDate: { $lte: threeDaysFromNow, $gte: new Date() } }).populate("userId"); for (const sub of expiringSubscriptions) { await sendEmail(sub.userId.email, "subscriptionExpiring", { firstName: sub.userId.firstName, endDate: sub.endDate, amount: sub.amount }); } console.log(`Sent ${expiringSubscriptions.length} renewal reminders`); });
6. Cache Warming
cron.schedule("0 5 * * *", async () => { console.log("Warming cache at 5 AM..."); // Pre-compute feed for active users const activeUsers = await User.find({ lastActiveAt: { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } }); for (const user of activeUsers) { const feed = await generateFeed(user._id); await redis.set(`feed:${user._id}`, JSON.stringify(feed), "EX", 3600); } console.log(`Cache warmed for ${activeUsers.length} users`); });
7. Log Rotation and Cleanup
cron.schedule("0 0 * * 0", async () => { console.log("Cleaning up old logs..."); const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // Delete old API logs await ApiLog.deleteMany({ timestamp: { $lt: thirtyDaysAgo } }); // Delete old email logs await EmailLog.deleteMany({ timestamp: { $lt: thirtyDaysAgo } }); // Compress or delete old PM2 logs const { exec } = require("child_process"); exec("pm2 flush", (err) => { if (err) console.error("PM2 log flush failed:", err); }); console.log("Log cleanup complete"); });
8. Health Check
cron.schedule("*/5 * * * *", async () => { try { // Check database connection await mongoose.connection.db.admin().ping(); // Check Redis connection (if used) await redis.ping(); // Update health status await redis.set("health:api", "ok", "EX", 300); } catch (err) { console.error("Health check failed:", err); await redis.set("health:api", "error", "EX", 300); // Send alert await sendAlert("API health check failed: " + err.message); } });
The Takeaway
Common cron job use cases include: data cleanup (delete old tokens, unverified users, old records), email notifications (daily digests, renewal reminders), report generation (weekly analytics), database backups (daily mongodump to S3), cache warming (pre-compute feeds), log rotation (delete old logs), and health checks (verify database and Redis connectivity). Schedule cleanup at midnight, notifications at 9 AM, and backups at 2 AM.
Data cleanup (delete old tokens, unverified users, expired records), email notifications (daily digests, renewal reminders), report generation (weekly analytics), database backups (daily mongodump to S3), cache warming, log rotation, and health checks (verify database and Redis connectivity).
Schedule a daily task at midnight (cron.schedule('0 0 * * *', ...)). Use MongoDB queries to delete documents older than a threshold: await User.deleteMany({ createdAt: { $lt: thirtyDaysAgo } }). Clean up expired tokens, unverified users, and old connection requests.
Schedule at 9 AM (cron.schedule('0 9 * * *', ...)). Find users with pending connection requests from the last 24 hours. For each user, send a digest email with their pending requests. Check emailBounced and emailComplained flags before sending.
Schedule at 2 AM (cron.schedule('0 2 * * *', ...)). Use child_process.exec to run mongodump with --uri and --archive --gzip flags. Upload the backup file to S3. Keep local backups for 7 days and S3 backups for 30 days.
Schedule every 5 minutes (cron.schedule('*/5 * * * *', ...)). Ping the database (mongoose.connection.db.admin().ping()), ping Redis if used, and update a health status key in Redis with a 5-minute TTL. Send an alert if any check fails.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

