Migrate to JobRunr

Switching to JobRunr is straightforward. Most migrations take a few hours, not days. Pick your starting point below.

The Fastest Path

Already have jobs defined as methods in your codebase? JobRunr works with your existing code.

  1. Add the JobRunr dependency
  2. Configure JobRunr (see the documentation)
  3. Schedule your jobs using the JobRunr API

Your job methods stay the same. Only the scheduling layer changes.

Migration Guides

From Quartz Scheduler Medium

2-4 hours for typical projects

Quartz requires Job classes, triggers, and complex configuration. JobRunr uses simple lambdas or JobRequest/JobRequestHandler.

BEFORE (Quartz)
JobDetail job = JobBuilder.newJob(EmailJob.class)
    .withIdentity("sendEmail")
    .usingJobData("userId", id)
    .build();

Trigger trigger = TriggerBuilder.newTrigger() .startNow() .build();
scheduler.scheduleJob(job, trigger);
AFTER (JobRunr)
BackgroundJob.enqueue(
    () -> emailService.send(userId)
);

What changes:

  • Remove Job interface implementations
  • Remove trigger configuration
  • Replace with lambda calls or job requests
  • Delete 11 Quartz tables, JobRunr manages its own schema

Full Quartz Migration Guide →

From Spring @Scheduled Easy

30 minutes to 1 hour

Spring @Scheduled is simple but doesn't persist jobs or handle multiple instances. JobRunr adds reliability.

BEFORE (Spring)
@Scheduled(cron = "0 0 9 * * *")
public void dailyReport() {
    reportService.generate();
}
AFTER (JobRunr)
@Recurring(id = "daily-report",
    cron = "0 0 9 * * *")
public void dailyReport() {
    reportService.generate();
}

What you gain:

  • Jobs survive application restarts
  • No duplicate execution across instances
  • Built-in dashboard and monitoring
  • Automatic retries on failure

Spring Boot Starter Configuration → | Java Scheduling Guide →

From Spring Batch Medium

Varies by complexity

Spring Batch is for ETL and chunk processing. JobRunr is for background tasks. You might need both, or just JobRunr.

Use JobRunr instead when:

  • You're processing items individually, not in chunks
  • You don't need reader/processor/writer pattern
  • You want simpler code without batch infrastructure

Keep Spring Batch when:

  • You're doing true ETL workloads
  • You need chunk-based transaction management
  • You're processing millions of records in a single job

Spring Batch vs JobRunr →

From Hangfire (.NET) Easy

1-2 hours (API is nearly identical)

Moving from .NET to Java? JobRunr's API was inspired by Hangfire. The concepts map directly.

Hangfire (.NET)
BackgroundJob.Enqueue(
    () => Console.WriteLine("Hello!")
);

BackgroundJob.Schedule( () => SendEmail(userId), TimeSpan.FromDays(7) );
JobRunr (Java)
BackgroundJob.enqueue(
    () -> System.out.println("Hello!")
);

BackgroundJob.schedule( Instant.now().plus(Duration.ofDays(7)), () -> sendEmail(userId) );

Hangfire for Java Guide →

From Custom/Homegrown Scheduler Varies

Depends on current implementation

Built your own job scheduler? Time to stop maintaining it.

Common patterns to replace:

  • Database polling loops → JobRunr handles this
  • Custom locking logic → Built into JobRunr
  • Retry mechanisms → Automatic with exponential backoff
  • Status tracking tables → JobRunr manages its own schema
  • Admin UI → Built-in dashboard

Why DIY Schedulers Fail →

Common Migration Questions

Can I run both during migration?

Yes. JobRunr doesn’t interfere with existing schedulers. You can migrate incrementally:

  1. Add JobRunr alongside existing scheduler
  2. Move jobs one by one
  3. Remove old scheduler when complete

What about my existing job data?

JobRunr creates its own tables. Your existing job history stays in the old system. For most teams, this is fine. Starting fresh with JobRunr’s cleaner data model is often preferred.

Do I need to change my job code?

Usually no. JobRunr calls your existing methods. You’re changing how jobs are scheduled, not what they do.

How do I handle in-flight jobs during migration?

  1. Stop creating new jobs with the old scheduler
  2. Wait for in-flight jobs to complete (monitor the old dashboard/logs)
  3. Switch to JobRunr for new jobs
  4. Shut down old scheduler

For recurring jobs, schedule them in JobRunr before removing from the old system to avoid gaps.