Quarkus Db Scheduler
A Quarkus extension that integrates db-scheduler with the Quarkus scheduler API. It provides persistent, cluster-friendly scheduling backed by a single database table.
Features
-
Full integration with
@Scheduledannotations fromquarkus-scheduler -
Persistent task storage using a single database table
-
Cluster-safe execution — only one node picks up a given task
-
Supports both cron expressions and fixed-interval schedules
-
Configurable polling interval, thread pool, and heartbeat
-
Pause and resume individual jobs or the entire scheduler
-
Access the underlying
com.github.kagkarlsson.scheduler.Schedulerfor advanced use cases
Installation
Add the extension dependency to your project.
You also need a JDBC driver extension (e.g. quarkus-jdbc-postgresql) and a configured datasource.
<dependency>
<groupId>io.quarkiverse.db-scheduler</groupId>
<artifactId>quarkus-db-scheduler</artifactId>
<version>0</version>
</dependency>
Database Setup
db-scheduler requires a single table in your database. Create it before starting the application.
PostgreSQL
create table scheduled_tasks (
task_name text not null,
task_instance text not null,
task_data bytea,
execution_time timestamp with time zone not null,
picked boolean not null,
picked_by text,
last_success timestamp with time zone,
last_failure timestamp with time zone,
consecutive_failures int,
last_heartbeat timestamp with time zone,
version bigint not null,
primary key (task_name, task_instance)
);
MySQL / MariaDB
create table scheduled_tasks (
task_name varchar(100) not null,
task_instance varchar(100) not null,
task_data blob,
execution_time timestamp(6) not null,
picked bit(1) not null,
picked_by varchar(50),
last_success timestamp(6) null,
last_failure timestamp(6) null,
consecutive_failures int,
last_heartbeat timestamp(6) null,
version bigint not null,
primary key (task_name, task_instance)
);
For MySQL and MariaDB, set quarkus.db-scheduler.always-persist-timestamp-in-utc=true.
|
Oracle
create table scheduled_tasks (
task_name varchar2(100) not null,
task_instance varchar2(100) not null,
task_data blob,
execution_time timestamp with time zone not null,
picked number(1) not null,
picked_by varchar2(50),
last_success timestamp with time zone,
last_failure timestamp with time zone,
consecutive_failures number(10),
last_heartbeat timestamp with time zone,
version number(19) not null,
primary key (task_name, task_instance)
);
DDL scripts for additional databases are available in the db-scheduler documentation.
Usage
Use @Scheduled annotations exactly as you would with the built-in Quarkus scheduler.
The extension automatically persists the schedules and ensures cluster-safe execution.
Fixed-Interval Schedule
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.scheduler.Scheduled;
@ApplicationScoped
public class MyJobs {
@Scheduled(every = "10s", identity = "my-recurring-job")
void everyTenSeconds() {
// persisted and cluster-safe
}
}
Advanced Usage
Injecting the db-scheduler Scheduler
For use cases not covered by @Scheduled (e.g. one-off tasks or programmatic scheduling), you can inject the underlying com.github.kagkarlsson.scheduler.Scheduler directly:
import com.github.kagkarlsson.scheduler.Scheduler;
@ApplicationScoped
public class AdvancedScheduling {
@Inject
Scheduler dbScheduler;
public void scheduleOneOff() {
// use the db-scheduler API directly
}
}
The Scheduler bean is only available when at least one @Scheduled method exists, or when the start mode is set to forced via quarkus.scheduler.start-mode=forced.
|
Pause and Resume
You can pause and resume individual jobs or the entire scheduler using the io.quarkus.scheduler.Scheduler API:
import io.quarkus.scheduler.Scheduler;
@ApplicationScoped
public class SchedulerControl {
@Inject
Scheduler scheduler;
public void pauseAll() {
scheduler.pause();
}
public void resumeAll() {
scheduler.resume();
}
public void pauseJob() {
scheduler.pause("my-recurring-job");
}
public void resumeJob() {
scheduler.resume("my-recurring-job");
}
}
Cluster Deployment
db-scheduler is designed for clustered environments. When multiple application instances share the same database, only one instance will execute a given task at any time.
Requirements for cluster operation:
-
All nodes must share the same database and
scheduled_taskstable -
All nodes must have reasonably synchronized clocks (NTP recommended)
-
All nodes should use the same polling interval
No additional configuration is needed — cluster-safe execution is the default behavior.
Extension Configuration Reference
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
|---|---|---|
The name of the datasource to use. If not specified, the default datasource is used. Environment variable: |
string |
|
Number of threads used by the scheduler. Environment variable: |
int |
|
How often the scheduler checks the database for due executions. Environment variable: |
|
|
How often the scheduler updates its heartbeat timestamp in the database. Environment variable: |
|
|
Maximum time to wait for running tasks to complete during shutdown. Environment variable: |
|
|
If set to Environment variable: |
boolean |
|
Always persist timestamps in UTC. Recommended for MySQL and MariaDB. Environment variable: |
boolean |
|
The name of the database table used by db-scheduler. Environment variable: |
string |
|
|
About the Duration format
To write duration values, use the standard You can also use a simplified format, starting with a number:
In other cases, the simplified format is translated to the
|