QueueCTL is a lightweight, production-style background job queue written in Go.
It provides persistent job storage, worker pools, automatic retries with exponential backoff, DLQ support, job logs, timeouts, lease recovery, and a clean CLI interface.
The system architecture for QueueCTL is illustrated below:
- Persistent job queue using SQLite
- Worker pool with configurable concurrency
- Exponential backoff retry mechanism
- Dead Letter Queue (DLQ) for permanent failures
- Graceful shutdown and lease-based recovery
- Command execution via
sh -c - Job output logging (stdout/stderr)
- Job timeouts
- Configurable retry/max-retry/backoff
- Requeueing expired worker leases
- Multi-worker concurrency without duplicate execution
- Structured CLI with Cobra
- Go 1.21+
- SQLite (optional, only if you want to manually inspect the DB)
Build the binary:
go build -o queuectl .(Optional) Install globally:
sudo mv queuectl /usr/local/bin/queuectl enqueue "echo hello" --db ./queue.dbqueuectl worker start --db ./queue.dbqueuectl list --state pending --db ./queue.dbqueuectl status --db ./queue.dbqueuectl logs <job-id> --db ./queue.dbqueuectl dlq list --db ./queue.db
queuectl dlq retry <job-id> --db ./queue.dbqueuectl config get --db ./queue.db
queuectl config set backoff_base 3 --db ./queue.db.
├── cmd/ # CLI commands (Cobra)
├── internal/
│ ├── core/ # Retry manager, worker logic
│ └── store/ # SQLite storage implementation
├── pkg/models/ # Job and config models
├── scripts/ # e2e and concurrency test scripts
└── queuectl (bin)
QueueCTL is built around four primary components:
Parses commands using Cobra and routes actions to storage or workers.
Handles:
- Job persistence
- Atomic
AcquireJobvia SQL transactions - Logs
- Config values
- DLQ transitions
- Retry Manager (exponential backoff)
- Worker loop
- Timeout enforcement
- Lease expiration reaper
- DLQ handling
Multiple goroutines or processes polling the storage, executing commands, and updating job state safely.
./scripts/e2e_test.sh./scripts/concurrency_test.shsqlite3 demo.db "SELECT state, COUNT(*) FROM jobs GROUP BY state;"- SQLite chosen for simplicity and robustness
- Workers rely on DB-level locking (serializable transactions)
- Jobs are executed through the shell for portability
- Backoff formula:
delay = base^attemptwith 5-minute cap - Lease timeout prevents stuck jobs when workers crash
- Scheduled jobs (
run_at) - Priority queues
- HTTP API / dashboard
- Job cancellation
- Distributed store (Postgres / Redis)
This project is licensed under the MIT License — see the LICENSE file for details.
