Skip to content

Durable job queues for Go

Background jobs, checkpointed multi-step workflows, fan-out/fan-in, 
crash recovery, and an embedded real-time dashboard — in a single import.

Go Reference CI Go Report Card Coverage GitHub stars
Works with SQLite PostgreSQL MySQL Go 1.25+
package main

import (
	"context"
	"fmt"

	jobs "github.com/jdziat/simple-durable-jobs/v4"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func main() {
	db, _ := gorm.Open(sqlite.Open("jobs.db?_journal_mode=WAL&_busy_timeout=5000&_txlock=immediate"), &gorm.Config{})
	storage := jobs.NewGormStorage(db)
	_ = storage.Migrate(context.Background())
	queue := jobs.New(storage)

	// Register a typed handler.
	queue.Register("greet", func(ctx context.Context, name string) error {
		fmt.Println("Hello,", name)
		return nil
	})

	// Enqueue work and start processing.
	queue.Enqueue(context.Background(), "greet", "world")
	jobs.NewWorker(queue).Start(context.Background())
}

Durable Workflows

Multi-step workflows with automatic checkpointing. If a workflow fails, it resumes from the last successful step instead of starting over.

Fan-Out / Fan-In

Spawn parallel sub-jobs, wait for results, and aggregate. Supports fail-fast, collect-all, and threshold strategies.

Crash Recovery

Jobs persist to a database and survive crashes. A stale-lock reaper automatically reclaims jobs stuck on dead workers.

Embedded Web UI

A real-time monitoring dashboard with stats, historical charts, live event streaming, and job management — mounted into your own HTTP server.

Scheduled Jobs

Cron expressions plus daily, weekly, and interval-based scheduling with a built-in scheduler.

Simple API

Minimal boilerplate, type-safe handlers, and a clean facade. Import one package and start processing jobs.

Transactional Enqueue

Enqueue inside your own database transaction so business rows and the jobs that act on them commit — or roll back — together. No dual-write race.

Durable Signals

Send, wait, check, and drain durable signals to coordinate jobs with each other and with the outside world — buffered, FIFO, and consumed exactly-once. (Handlers themselves are at-least-once; keep side effects idempotent.)

Dead-Letter Queue

Jobs that exhaust retries (or hit a non-retryable error) carry explicit dead-letter metadata you can list, count, inspect, and requeue.

Rate Limiting

Throttle execution with per-queue token buckets and an optional fleet-wide limiter, and cap concurrency fleet-wide or per key — without burning retry attempts.

Prometheus / OTel Metrics

Opt into an exporter for queue depth, throughput, wait and run latency, attempts, failures, and retries — scrapeable for alerting and capacity planning.

Payload Encryption

Plug in a codec to transparently encrypt job arguments, results, checkpoints, and error text (last_error / dead-letter reason) at rest, with key rotation, at the storage boundary. (opt-in; encrypts the listed fields at the application/storage boundary — it is not whole-database encryption and is not a compliance attestation.)