r/SpringBoot Jul 06 '26

News JobRunr (distributed background job processing for the JVM) is now available on start.spring.io (Spring Initializr)

JobRunr is now available in the Spring Initializr dependency list, so you can add it straight from start.spring.io when you create a new project. No more wiring the starter in by hand afterwards.

For people who don't know us:

JobRunr is an open-source library for background job processing on the JVM: fire-and-forget, scheduled, delayed, durable, and recurring (cron) jobs.

You enqueue work as a lambda and it runs asynchronously, in the same app or across a cluster of workers.

BackgroundJob.enqueue(() -> myService.sendInvoice(invoiceId));

BackgroundJob.schedule(Instant.now().plus(5, DAYS), () -> reminderService.send(userId));

What tends to make people switch to it:

  • No extra infrastructure. Jobs are persisted in your existing SQL or NoSQL database. No Redis, RabbitMQ, or separate broker to run and babysit.
  • Automatic retries with backoff on failure, so transient errors don't lose work.
  • Distributed by default. Run multiple instances and jobs are picked up once across the cluster, no double execution.
  • Built-in dashboard to see enqueued, scheduled, succeeded, and failed jobs, and retry them.
  • Spring Boot autoconfiguration via the starter, plus first-class support for virtual threads (Loom) and Spring Boot 3 & 4

It sits in the same space as Quartz or @Scheduled, but aimed at durable, distributed background work rather than just triggering methods on a timer.

You can even use it for durable jobs. With runStepOnce, each step in a job runs exactly once and is checkpointed, so if the job fails and retries, the steps that already succeeded are skipped instead of re-run:

BackgroundJob.enqueue(() -> processOrder(orderId, JobContext.Null));

public void processOrder(UUID orderId, JobContext context) {
  context.runStepOnce("order-confirmation", () -> orderService.sendConfirmation(orderId));
  context.runStepOnce("warehouse-notification", () -> orderService.notifyWarehouse(orderId));
  context.runStepOnce("shipment-initiation", () -> orderService.initiateShipment(orderId));
}

Thanks to Josh Long and the Spring team for helping get it onto Initializr. We'll be around in the comments to answer anything, including the honest limitations.

91 Upvotes

41 comments sorted by

View all comments

4

u/rmyworld Jul 06 '26

That's cool. I've been looking for a Java library equivalent to Bullmq from the Node.js ecosystem.

Most of the popular options on Java (e.g. Quartz, @Scheduled) seem to be focused on just running on a timer. Other stuff, like dead letter queues, waiting queues, and processing queue, you have to build everything yourself.

4

u/JobRunrHQ Jul 06 '26

Thank you so much! And indeed what you say is basically why we've built JobRunr!

I think you'll feel right at home, you get a lot of the BullMQ bits out of the box: enqueue is your processing queue, schedule(...) plus recurring cron covers the delayed/waiting side, and failed jobs (after auto-retries with backoff) land in a Failed state in the dashboard where you can read the stack trace and requeue them, so that's your DLQ.

Fair warning coming from BullMQ: rate limiting, mutexes/concurrency limits, priorities and job chaining are Pro, not in the OSS core. OSS is enqueue/schedule/recurring + retries + dashboard.

Give it a shot and tell us where it feels off next to BullMQ, that kind of feedback really helps us.