Advanced Scheduling Patterns
Learn about complex scheduling patterns, cron syntax, and best practices for optimizing your CronJS job schedules.
Cron Expression Fundamentals
CronJS uses standard 5-field cron expressions:
minute hour day month day-of-week
| | | | |
| | | | ββ Day of week (0-6, 0=Sunday)
| | | ββββββββββββ Month (1-12)
| | βββββββββββββββββ Day of month (1-31)
| ββββββββββββββββββββββ Hour (0-23)
ββββββββββββββββββββββββββββ Minute (0-59)
Basic Examples
# Every minute
* * * * *
# Every hour at minute 0
0 * * * *
# Every day at 2:30 AM
30 2 * * *
# Every Monday at 9:00 AM
0 9 * * 1
# Every 15 minutes
*/15 * * * *
Visual Cron Builder
CronJS provides three ways to create schedules:

1. Preset Patterns
Choose from common scheduling patterns:
- Every 5 minutes -
*/5 * * * *
- Daily at 9 AM -
0 9 * * *
- Weekly on Monday -
0 9 * * 1
- Monthly on 1st -
0 9 1 * *
- Hourly -
0 * * * *
2. Visual Builder
Use the interactive interface to:
- Select minute intervals with dropdowns
- Choose specific hours or hour ranges
- Pick days of the month or week
- Set monthly patterns
- Preview the resulting cron expression
3. Manual Expression
For advanced users, write cron expressions directly with:
- Real-time validation
- Syntax highlighting
- Human-readable translation
- Error detection and suggestions
Common Scheduling Patterns
Business Hours Monitoring
# Every 5 minutes during business hours (9 AM - 5 PM, Mon-Fri)
*/5 9-17 * * 1-5
// Example: API health check during business hours
const response = await fetch("https://api.yourcompany.com/health");
if (!response.ok) {
console.error("API health check failed during business hours");
// Send immediate alert
}
Daily Reports
# Daily at 6 AM
0 6 * * *
// Example: Generate daily summary report
const today = new Date().toISOString().split("T")[0];
console.log(`Generating daily report for ${today}`);
const report = await generateDailyMetrics();
await sendEmailReport(report);
Weekly Maintenance
# Every Sunday at 2 AM
0 2 * * 0
// Example: Weekly database cleanup
console.log("Starting weekly maintenance...");
await cleanupOldLogs();
await optimizeDatabase();
await generateWeeklyReport();
console.log("Weekly maintenance completed");
High-Frequency Monitoring
# Every 2 minutes
*/2 * * * *
// Example: Critical service monitoring
const services = [
"https://api.payment.com/status",
"https://api.auth.com/health",
"https://api.core.com/ping",
];
for (const service of services) {
const response = await fetch(service);
if (!response.ok) {
console.error(`Service down: ${service}`);
// Immediate notification
}
}
Monthly Tasks
# First day of every month at 1 AM
0 1 1 * *
// Example: Monthly billing report
const month = new Date().getMonth() + 1;
const year = new Date().getFullYear();
console.log(`Generating monthly report for ${month}/${year}`);
const billingData = await generateMonthlyBilling();
await sendMonthlyInvoices(billingData);
Advanced Patterns
Multiple Time Windows
# Twice daily: 6 AM and 6 PM
0 6,18 * * *
Specific Days
# Every Tuesday and Thursday at 10:30 AM
30 10 * * 2,4
Month-End Processing
# Last day of every month at 11 PM
0 23 28-31 * *
Note: This runs on days 28-31, but the job should check if itβs actually the last day of the month
// Check if today is the last day of the month
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
if (tomorrow.getMonth() !== today.getMonth()) {
console.log("Running month-end processing...");
await processMonthEndTasks();
}
Seasonal Schedules
# Every day at 8 AM during summer months (June-August)
0 8 * 6-8 *
Working Days Only
# Every 30 minutes, Monday through Friday
*/30 * * * 1-5
Time Zone Considerations
Default Behavior
CronJS runs all schedules in UTC (Coordinated Universal Time) by default.
Handling Different Time Zones
Since schedules run in UTC, convert your local time to UTC:
// If you want 9 AM Eastern Time (UTC-5 in winter, UTC-4 in summer):
// Winter: 9 AM EST = 2 PM UTC
// Summer: 9 AM EDT = 1 PM UTC
// For consistent 9 AM Eastern Standard Time (UTC-5):
// Use: 0 14 * * * (2 PM UTC = 9 AM EST)
Dynamic Time Zone Handling
Handle time zones in your job code:
// Get current time in specific timezone
const now = new Date();
const easternTime = new Date(
now.toLocaleString("en-US", { timeZone: "America/New_York" })
);
console.log("UTC Time:", now.toISOString());
console.log("Eastern Time:", easternTime.toLocaleString());
// Only run during business hours in Eastern time
const hour = easternTime.getHours();
if (hour >= 9 && hour <= 17) {
console.log("Running business hours task...");
await runBusinessHoursTask();
} else {
console.log("Outside business hours, skipping task");
}
Performance Optimization
Avoid High-Frequency Jobs
# β Avoid: Every second (not supported)
* * * * * *
# β Avoid: Every minute for non-critical tasks
* * * * *
# β
Better: Every 5 minutes for monitoring
*/5 * * * *
# β
Better: Every 15 minutes for data sync
*/15 * * * *
Stagger Multiple Jobs
Instead of scheduling multiple jobs at the same time:
# β All jobs at top of hour
0 * * * * # Job A
0 * * * * # Job B
0 * * * * # Job C
# β
Stagger execution times
0 * * * * # Job A at :00
15 * * * * # Job B at :15
30 * * * * # Job C at :30
Resource-Aware Scheduling
Consider resource usage when scheduling:
// Heavy processing job - run during low-traffic hours
// Schedule: 0 3 * * * (3 AM UTC)
console.log("Starting resource-intensive task...");
const startTime = Date.now();
await processLargeDataset();
await generateComplexReport();
const duration = Date.now() - startTime;
console.log(`Task completed in ${duration}ms`);
Error Handling in Scheduled Jobs
Retry Logic
async function robustApiCall(url, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url);
if (response.ok) {
return await response.json();
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw new Error(`All ${maxRetries} attempts failed`);
}
// Wait before retry (exponential backoff)
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
}
}
}
// Usage in scheduled job
try {
const data = await robustApiCall("https://api.example.com/data");
console.log("Data retrieved successfully:", data);
} catch (error) {
console.error("Failed to retrieve data after retries:", error.message);
// Handle final failure (send alert, log to external service, etc.)
}
Graceful Degradation
// Handle partial failures gracefully
const tasks = [
{ name: "Task A", fn: taskA },
{ name: "Task B", fn: taskB },
{ name: "Task C", fn: taskC },
];
const results = [];
for (const task of tasks) {
try {
const result = await task.fn();
results.push({ task: task.name, status: "success", result });
console.log(`β
${task.name} completed successfully`);
} catch (error) {
results.push({ task: task.name, status: "failed", error: error.message });
console.error(`β ${task.name} failed:`, error.message);
// Continue with other tasks
}
}
// Report overall results
const successful = results.filter((r) => r.status === "success").length;
const failed = results.filter((r) => r.status === "failed").length;
console.log(`Job Summary: ${successful} successful, ${failed} failed`);
Best Practices
1. Start Conservative
# β
Start with longer intervals
0 */6 * * * # Every 6 hours
# β
Increase frequency if needed
0 */3 * * * # Every 3 hours
*/30 * * * * # Every 30 minutes
2. Monitor Job Duration
const startTime = Date.now();
// Your job logic here
await performTasks();
const duration = Date.now() - startTime;
console.log(`Job completed in ${duration}ms`);
// Alert if job takes too long
if (duration > 300000) {
// 5 minutes
console.warn("Job took longer than expected");
}
3. Use Meaningful Schedules
# β
Good: Align with business needs
0 9 * * 1-5 # Business hours start
0 17 * * 1-5 # Business hours end
0 0 * * 1 # Weekly Monday morning
# β Avoid: Random intervals
*/13 * * * * # Every 13 minutes (why?)
4. Document Your Schedules
/**
* Daily Report Generation
* Schedule: 0 6 * * * (Every day at 6 AM UTC)
* Purpose: Generate and email daily metrics report
* Dependencies: Database, Email service
* Estimated runtime: 2-5 minutes
*/
console.log("Starting daily report generation...");
// Job implementation
Common Mistakes to Avoid
1. Time Zone Confusion
# β Thinking this runs at 9 AM local time
0 9 * * *
# β
Remember: This runs at 9 AM UTC
# For 9 AM EST, use: 0 14 * * *
2. Overlapping Executions
# β Job that takes 2 hours scheduled every hour
0 * * * *
# β
Ensure jobs complete before next execution
0 */3 * * * # Every 3 hours instead
3. Peak Time Scheduling
# β Heavy jobs during peak hours
0 12 * * * # Noon UTC (busy time for many regions)
# β
Schedule during off-peak hours
0 3 * * * # 3 AM UTC (typically low traffic)
Testing Your Schedules
Validate Cron Expressions
Use the visual builder to verify your expressions:
- Enter your cron expression
- Check the human-readable translation
- Verify the next few execution times
- Test with βRun Nowβ before deploying
Monitoring Schedule Adherence
// Log execution times to verify schedule adherence
const now = new Date();
console.log(`Job executed at: ${now.toISOString()}`);
console.log(
`UTC time: ${now.getUTCHours()}:${now
.getUTCMinutes()
.toString()
.padStart(2, "0")}`
);
// Expected vs actual execution time
const expectedMinute = 0; // If scheduled for top of hour
const actualMinute = now.getUTCMinutes();
const delay = actualMinute - expectedMinute;
if (delay > 1) {
console.warn(`Job started ${delay} minutes late`);
}
Next Steps
- Job Management Guide - Learn to manage scheduled jobs effectively
- Monitoring & Logging - Track job execution and performance
- Troubleshooting - Solve common scheduling issues
- Getting Started - Create your first scheduled job
Master these scheduling patterns to build reliable, efficient automation with CronJS! π