asynqpg v0.1.4
github.com/yakser/asynqpg · v0.1.4

Distributed task queue for Go,
backed by Postgres.

Consumers pull tasks concurrently without contention – Postgres hands each worker its own batch and skips rows already claimed by others, so throughput scales with workers. Producers can enqueue inside the same transaction as your business logic, so a job appears if and only if your write commits.

go.devreference go1.25+ postgres14+ license MIT
4
GitHub stars
v0.1.4
latest release
18 open
issues & PRs
Capabilities

Built for production task queues.

No magic. Every feature maps to one or two columns in asynqpg_tasks or a small SQL pattern.

Postgres-native

Tasks live in a single table. No Redis, no Kafka, no new datastore to operate.

Transactional enqueue

Pass an *sqlx.Tx to EnqueueTx. The job is committed atomically with your business logic.

Flexible retries

Exponential or constant backoff, snooze without consuming an attempt, skip-retry for permanent errors.

Delayed & scheduled

Run tasks at a future time. WithDelay, or set ProcessAt directly on the task.

Per-type worker pools

Independent concurrency, timeout, and middleware per task type. email:send can have 5 workers, report:generate can have 2.

Leader-elected maintenance

One node holds a lease. Stuck-task rescue and old-task cleanup run there. The other nodes just fetch.

Idempotency tokens

EnqueueMany deduplicates by (type, idempotency_token) at the DB layer, not in code.

OpenTelemetry built in

Counters, histograms, and traces for every enqueue and handler call. SpanKind set correctly for each.

Web dashboard

Embedded React SPA with Overview, Tasks, Workers, and Maintenance pages. Saved views, filter pills, bulk retry/cancel/delete, and a task drawer with payload, attempts, timing, and the raw row.

Command palette & keyboard nav

⌘K jumps to any task, type, or page. j/k walks the table, x selects, Esc closes the drawer – no mouse required.

Pluggable auth

Basic Auth out of the box, or wire up any number of OAuth providers (GitHub ships in-tree). Per-request user context flows into audit logs.

Quickstart

Five minutes from zero to a working task queue.

Three steps: install the module, apply one migration, write a producer and a consumer. No infra to provision.

01

Install the module

Adds asynqpg to your Go workspace.

02

Apply the migration

One SQL file. Creates asynqpg_tasks + indexes.

03

Wire a producer

Pass a *sqlx.DB. Call Enqueue. Done.

04

Wire a consumer

Register a handler per task type. Start().

$ go get github.com/yakser/asynqpg
Tip. Pass EnqueueTx the same tx as your business logic. The queued job commits if (and only if) your transaction commits. Try doing that with Redis.
Architecture

A queue is a table.

Five lifecycle states. One row per task. Workers pull jobs concurrently without stepping on each other – Postgres locks the rows it hands out and lets the rest move on, so no two consumers ever grab the same task and idle workers are never blocked by busy ones.

Packages

PackagePurpose
producer/ Enqueue tasks. Enqueue, EnqueueTx, EnqueueMany, EnqueueManyTx.
consumer/ Fetch and process tasks with configurable per-type worker pools. Middleware. Snooze, skip-retry, custom retry policies.
client/ Inspect and manage tasks. GetTask, ListTasks, CancelTask, RetryTask, DeleteTask. All have *Tx variants.
ui/ HTTP handler serving REST API + embedded React SPA dashboard. Basic Auth or pluggable OAuth providers.
internal/leadership/ Postgres-leased leader election. The leader runs maintenance.
internal/maintenance/ Stuck-task rescuer + finalized-task cleaner. Leader-only. Off by default.
Web UI

A dashboard built for operators.

An embedded React SPA. Mount it as an HTTP handler under any prefix, or run the standalone binary. Basic Auth or pluggable OAuth providers, your choice.

asynqpg Overview page – KPI strip with pending, running, failed, completed and cancelled counts; per-type queue cards sorted by failed desc.

Five live KPIs across all task types. Per-type cards show pending/running/done/failed/cancelled counts and link straight into the filtered Tasks list. Auto-refresh every 5s.

Note. The dashboard ships as a separate Go module so its frontend dependencies don't leak into your service. Mount it under any prefix, behind your own router and middleware.
Observability

OpenTelemetry, end to end.

All public components accept optional MeterProvider and TracerProvider. A pre-built Grafana dashboard ships in deploy/.

MetricTypeDescription
asynqpg.tasks.enqueued counter Tasks enqueued, tagged by task_type.
asynqpg.tasks.processed counter Tasks finished, tagged by task_type and status.
asynqpg.tasks.errors counter Processing or enqueue errors.
asynqpg.task.duration histogram Handler execution latency (seconds). p50/p95/p99 in the Grafana panel.
asynqpg.task.enqueue_duration histogram Enqueue latency (seconds).
asynqpg.tasks.in_flight gauge Currently executing tasks.