The rdq CLI
rdq is the ops CLI: a single Go binary for queue stats, DLQ
browse/inspect/redrive/purge, and schema migrations. It is the on-call
engineer’s primary tool until the web UI ships.
Two transports
Section titled “Two transports”Every command runs in one of two modes.
API mode (--server URL) — an ordinary client of the public rdq-server REST
API. All commands go through /v1; no server internals are imported. Add
--token for authenticated servers.
rdq --server http://rdq-server:8080 stats my-queuerdq --server http://rdq-server:8080 --token $TOKEN dlq list my-queueDirect-storage mode (--dsn DSN) — talks straight to Postgres via the
storage plugin. No rdq-server needed; ideal for embedded deployments and one-off
maintenance.
rdq --dsn "postgres://rdq:rdq@localhost:5432/rdq?sslmode=disable" stats my-queuerdq stats <queue>
Section titled “rdq stats <queue>”Print a per-queue operational snapshot — the numbers you page on:
rdq --server http://rdq-server:8080 --token $TOKEN stats my-queueQueue: my-queuePending: 42In-flight: 3DLQ depth: 7Oldest pending age: 4m12sDLQ depth and Oldest pending age are the two flagship signals — see
observability & metrics.
rdq dlq list <queue> [flags]
Section titled “rdq dlq list <queue> [flags]”Page the dead-letter queue.
| Flag | Description |
|---|---|
--limit N | Tasks per page (default 20) |
--cursor C | Pagination cursor from a prior listing |
--error-type E | Filter by final-attempt error type |
--handler-ref H | Filter by handler ref |
--from RFC3339 | Dead-lettered at or after this time (inclusive) |
--to RFC3339 | Dead-lettered before this time (exclusive) |
rdq --server URL --token $TOKEN dlq list payments.charge \ --error-type java.net.SocketTimeoutException \ --from 2026-07-27T14:00:00Z --limit 50rdq dlq inspect <id>
Section titled “rdq dlq inspect <id>”Print the full envelope — all fields plus the complete attempt history — for one task as JSON:
rdq --server URL --token $TOKEN dlq inspect 01J2ZK7Q...{ "id": "01J2ZK7Q...", "queue": "payments.charge", "handler_ref": "charge-payment", "status": "DEAD", "attempt_count": 3, "attempts": [ { "attempt_no": 1, "outcome": "RETRYABLE_FAILURE", "error_type": "java.net.SocketTimeoutException", "error_message": "connect timed out" }, { "attempt_no": 2, "outcome": "RETRYABLE_FAILURE", "error_type": "java.net.SocketTimeoutException", "error_message": "connect timed out" }, { "attempt_no": 3, "outcome": "RETRYABLE_FAILURE", "error_type": "java.net.SocketTimeoutException", "error_message": "connect timed out" } ]}rdq dlq redrive <queue> [flags]
Section titled “rdq dlq redrive <queue> [flags]”Move matching DLQ tasks back to PENDING — attempt_count reset,
redrive_count incremented. Supply --id flags or filter flags, not both.
# by idrdq --dsn DSN dlq redrive my-queue --id abc123 --id def456
# by filterrdq --dsn DSN dlq redrive my-queue --error-type com.example.TransientErrorredriven 128 task(s) from my-queuerdq dlq purge <queue> [flags]
Section titled “rdq dlq purge <queue> [flags]”Permanently remove matching DLQ tasks — same selector shape as redrive:
rdq --dsn DSN dlq purge my-queue --handler-ref legacy.handlerrdq --dsn DSN dlq purge my-queue --id abc123Redrive and purge are audit-logged (principal, selector, count). Against a
server they require the operator role or higher. See
DLQ analysis & redrive.
rdq migrate
Section titled “rdq migrate”Apply the Postgres schema migrations (direct-storage mode only). Idempotent — safe to call on every startup:
rdq --dsn "postgres://rdq:rdq@db:5432/rdq?sslmode=disable" migratecd cligo build -o rdq .