Spring Boot Schedulers Job – Real-World Examples & Guide

In many applications, we need to run background jobs — like sending reminders, syncing data, or cleaning logs. Spring Boot provides a very simple way to schedule such tasks using the @Scheduled annotation.


🚀 Enable Scheduling in Spring Boot

Just add @EnableScheduling in your main class:

@SpringBootApplication
@EnableScheduling
public class CodingBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(CodingBootApplication.class, args);
    }
}

🛠️ Example 1: Run Task Every 10 Seconds

@Component
public class MyScheduler {

    @Scheduled(fixedRate = 10000) // runs every 10 sec
    public void printMessage() {
        System.out.println("Running scheduled task at " + LocalDateTime.now());
    }
}
  • fixedRate = 10000 → runs the task every 10 seconds after the previous start

🕒 Example 2: Run Task Daily at 2 AM (Using Cron)

@Component
public class DailyJobScheduler {

    @Scheduled(cron = "0 0 2 * * *")
    public void runDailyJob() {
        System.out.println("Running daily cleanup at 2 AM");
    }
}

📌 Cron Format in Spring (6 fields):

second minute hour day-of-month month day-of-week

Example: 0 0 2 * * * → at 2:00:00 AM every day

  • second: 0–59
  • minute: 0–59
  • hour: 0–23
  • day-of-month: 1–31
  • month: 1–12 (or JAN–DEC)
  • day-of-week: 0–6 (or SUN–SAT), where 0 = Sunday

🔁 Common Cron Examples:

  • Every 5 minutes:0 */5 * * * *
  • Every 30 minutes:0 */30 * * * *
  • Every hour at 15th minute:0 15 * * * *
  • Every day at midnight:0 0 0 * * *
  • Every Monday at 8:30 AM:0 30 8 * * MON

🧹 Example 3: Cleanup Task Every Midnight

@Component
public class CleanupScheduler {

    @Scheduled(cron = "0 0 0 * * ?")
    public void clearTempFiles() {
        // pretend to delete temp files
        System.out.println("[Midnight Cleanup] Temp files cleared");
    }
}

📦 YAML-Based Control (Recommended)

Instead of hardcoding cron in code, read it from application.yml:

scheduler:
  cleanup:
    cron: "0 0 0 * * ?"

Now use:

@Component
@RequiredArgsConstructor
public class ConfigurableScheduler {

    private final Environment environment;

    @Scheduled(cron = "#{'${scheduler.cleanup.cron}'}")
    public void run() {
        System.out.println("[YAML Scheduler] Running at configured time");
    }
}

🔄 fixedDelay vs fixedRate vs Async in spring boot scheduler jobs

AttributeBehavior
fixedRateRuns every X ms from start time
fixedDelayRuns every X ms after previous completes
@Scheduled(fixedDelay = 5000) // runs after 5 sec of last execution end

💡 What happens if your task takes long time?

Let’s say your task takes 15 seconds to complete.

  • With fixedRate = 10000 // we can also write 10_000 for readability (10 sec):
    • The second execution will start even if the previous one is not finished.
    • This may result in overlapping executions if the task is slow.
  • With fixedDelay = 10000 // we can also write 10_000 for readability:
    • It will wait for the current task to finish.
    • Then wait 10 sec, then run again.
    • This is safer for long-running jobs.
  • With cron expression:
    • Cron triggers the task at the exact specified time, even if the previous task is still running.
    • So if your job takes longer than the cron interval, you may get multiple overlapping executions.
    • Spring does not stop or queue it. You must manually handle overlaps if needed.
  • With @Async:
    • If you annotate your scheduled method with @Async, it runs in a separate thread.
    • This is useful when you don’t want the main thread to wait.
    • But it also means your job runs in parallel, so you need to handle overlaps or shared resource issues manually.
    Example:@Async @Scheduled(fixedRate = 10000) public void runAsyncJob() { // runs asynchronously every 10 seconds }
    • Also add @EnableAsync in your main config class.
    @SpringBootApplication @EnableAsync @EnableScheduling public class AppMain {}

🔁 What Happens in Multiple App Instances?

If your Spring Boot app is running in a cluster or has multiple pods/instances, then:

  • Each instance will execute the scheduled task independently.
  • That means if 3 instances are running, your task will run 3 times at same time.

💡 To avoid duplicate runs in such setup:

  • Use distributed locks (like Redis-based lock or DB-based lock)
  • Example: ShedLock — popular lib to manage single-instance execution

⚠️ Common Mistakes in spring boot schedulers job

  • ❌ Forgetting @EnableScheduling
  • ❌ Using @Scheduled on private methods (must be public)
  • ❌ Cron format mismatch (watch day-of-week and month)
  • ❌ Not handling overlaps in multi-instance deployments


❗ Error Handling in Spring boot Schedulers job

If a scheduled method throws an exception and it’s not caught, it may silently fail or stop future executions in some thread pools.

To prevent this, always wrap your logic inside a try-catch block:

@Scheduled(fixedDelay = 10000)
public void runTask() {
    try {
        // your business logic
    } catch (Exception e) {
        log.error("Scheduled job failed", e);
        // optionally send alert/email/slack notification
    }
}

🧪 Testing Scheduled Jobs

  • You can reduce the delay time in @Scheduled while testing locally (like 2-3 seconds).
  • If your job depends on DB or services, consider mocking them to isolate logic.
  • Unit testing can be done by extracting the logic into a separate service method.

🚫 Disabling or Controlling Jobs via Config

Sometimes you don’t want a scheduler to run in a certain environment (like staging or test). You can control it from application.yml:

scheduler:
  enabled: false

Use this with @ConditionalOnProperty:

@Component
@ConditionalOnProperty(name = "scheduler.enabled", havingValue = "true")
public class MyConditionalJob {

    @Scheduled(cron = "0 0 1 * * *")
    public void run() {
        System.out.println("Running only if enabled=true in config");
    }
}

📊 Monitoring Spring boot Schedulers job

If you’re running jobs in production, it’s good to send trace logs to tools like:

  • 📈 Splunk
  • 📊 Kibana
  • 📬 Email or Slack (for alerts)

You can also use MDC or logging frameworks to include trace IDs:

MDC.put("traceId", UUID.randomUUID().toString());
log.info("Job started");

This helps in tracking logs when multiple jobs are running.


📚 Reference


✅ Summary

  • Use @Scheduled for simple job scheduling in Spring Boot
  • Understand difference between fixedRatefixedDelay, and cron
  • If job runs long, prefer fixedDelay
  • If deploying on multiple servers, ensure one instance runs the job using locking (like ShedLock)
  • YAML-based cron expressions give you config flexibility