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.
- Add the JobRunr dependency
- Configure JobRunr (see the documentation)
- 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.
JobDetail job = JobBuilder.newJob(EmailJob.class)
.withIdentity("sendEmail")
.usingJobData("userId", id)
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.build();
scheduler.scheduleJob(job, trigger);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
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.
@Scheduled(cron = "0 0 9 * * *")
public void dailyReport() {
reportService.generate();
}@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
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.
BackgroundJob.Enqueue(
() => Console.WriteLine("Hello!")
);
BackgroundJob.Schedule(
() => SendEmail(userId),
TimeSpan.FromDays(7)
);BackgroundJob.enqueue(
() -> System.out.println("Hello!")
);
BackgroundJob.schedule(
Instant.now().plus(Duration.ofDays(7)),
() -> sendEmail(userId)
);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
Common Migration Questions
Can I run both during migration?
Yes. JobRunr doesn’t interfere with existing schedulers. You can migrate incrementally:
- Add JobRunr alongside existing scheduler
- Move jobs one by one
- 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?
- Stop creating new jobs with the old scheduler
- Wait for in-flight jobs to complete (monitor the old dashboard/logs)
- Switch to JobRunr for new jobs
- Shut down old scheduler
For recurring jobs, schedule them in JobRunr before removing from the old system to avoid gaps.
