Skip to content
NewJoobQ Pro 0.4.1 runs on JoobQ 0.5.6.Build your first workflow

Open source corePro workflowsSelf-hosted console

Type-safe job queues & durable workflows.

Start with open-source Redis queues in Crystal, and run workers in Python, TypeScript, Ruby, Go, Rust, Java, PHP or .NET through the SDK gateway of a self-hosted JoobQUI. Scale to event-sourced sagas, deterministic replay and a real-time operator console.

  • Self-hostedJobs, workers and data stay in your network; only a licence check-in leaves it.
  • MIT coreThe JoobQ queue is open source.
  • RBAC · SSO · TOTPThree roles, OpenID Connect, two-factor.
  • Audit logA row for every state change.
crystal
>= 1.22.0
joobq
0.5.6
joobq_pro
0.4.1
~/billing — joobq workbench
Define a JobJoobQ · OSS
# worker.cr (excerpt): a job with a sealed field
struct SealedJob
  include JoobQ::Job

  @queue = SEALED
  @retries = 3
  @max_retries = 3
  @expires = 1.day.from_now.to_unix_ms

  property probe : String = ""
  property enqueued_before_ms : Int64 = 0_i64
  encrypted_property card_number : String = "", job_name: "Conf::SealedJob"

  def initialize
  end

  def initialize(@probe : String, @card_number : String, @enqueued_before_ms : Int64 = 0_i64)
  end

  def perform
    Conf.report("sealed", probe, {"card_sha256" => Conf.any(Digest::SHA256.hexdigest(card_number)), "enqueued_before_ms" => Conf.any(enqueued_before_ms)})
  end
end

# ...and, in another job's perform, a delayed enqueue of it
when "conf.produce"
  before = Conf.now_ms # before the call: the delay counts from when the job is stored
  jid = SealedJob.delay(for: 1.5.seconds, probe: probe, card_number: card_number, enqueued_before_ms: before)
  Conf.report("produce", probe, {"jid" => Conf.any(jid.to_s)})

A typed Crystal job with an AES-256-GCM sealed field, and a delayed enqueue of it. MIT licensed; tested against a real server.

mainAES-256-GCM sealed fieldretries: 3delayed enqueue 1.5 s

Engineering guarantees

Architecture specs, not adjectives

  • Encryption01

    AES-256-GCM field-level sealing

    Chosen job fields are sealed before they are stored: at rest in Redis, backups, dead letters and the console. Key rotation built in.

    • encrypted_property
    • encrypted_fields
    • JOOBQUI_PAYLOAD_KEYS
  • Worker ecosystem02

    Crystal native + 8 SDK languages

    Python, TypeScript, Go, Rust, Ruby, Java, PHP and .NET workers long-poll the SDK gateway; they never hold Redis credentials.

    • joobq
    • joobq_pro
    • /api/v1/sdk
  • Auth & governance03

    3-role RBAC · OIDC SSO · TOTP

    viewer, operator and admin enforced on every route; OpenID Connect single sign-on, TOTP two-factor and an audit row for every state change.

    • viewer
    • operator
    • admin
    • audit log
  • Deployment04

    One docker compose stack

    The server and PostgreSQL, with Redis (bundled or your own) and Caddy for HTTPS as optional profiles. Settings and licence persist in a /data volume.

    • selfhosted.compose.yml
    • --profile redis
    • --profile https

One ecosystem, three steps

Start with the open-source queue. Add what you need when you need it.

  1. Step 01: JoobQ · OSSOpen source · MIT

    JoobQ

    Redis-backed job queues, native to Crystal, with typed jobs and nothing else to run.

    • Typed JoobQ::Job structs, per-queue workers and throttles
    • Exponential-backoff retries and a dead-letter set
    • Delayed, recurring and cron jobs
    • AES-256-GCM encrypted_property job fields
    • A REST management API, off by default, behind bearer tokens
    Quickstart
  2. Step 02: JoobQ ProCommercial shard · Pro key

    JoobQ Pro

    A durable workflow engine and production extensions on top of the same queues. Every Pro feature checks a Pro key.

    • Workflows whose state is a fold of an append-only Redis history
    • Sagas: compensations run newest first on failure or cancel
    • Signals, timers, queries, child workflows, continue-as-new; updates and scopes in Crystal
    • Deterministic replay, versioning gates and worker build ids
    • Batches with callbacks, unique jobs, rate limits, metrics and alerting
    First workflow
  3. Step 03: JoobQUISelf-hosted console · licensed

    JoobQUI

    An operator console and SDK gateway you run next to your workers, with your data in your database. Licensed through the portal: Sign in with JoobQ once, no key to paste.

    • Live KPIs, queues, jobs and dead letters over a WebSocket stream
    • Workflow graph, event history with time travel, bulk actions
    • Viewer / operator / admin roles, API tokens and an audit log
    • TOTP two-factor and OpenID Connect single sign-on
    • The SDK gateway for workers in 8 more languages, /metrics and an OpenAPI 3.1 /api/v1
    Deploy it

Queues

Background jobs, native in Crystal.

In Crystal, jobs are structs checked by the compiler. JoobQ keeps them in Redis, runs them on fibers, and stops cleanly on SIGTERM. Workers in the other 8 languages reach the same queues through the SDK gateway of a self-hosted JoobQUI: they long-poll it over HTTPS and never connect to Redis.

Nine languages

Workers in the language your service is written in.

Crystal jobs and workflows run natively on the JoobQ shards. Python, TypeScript, Ruby, Go, Rust, Java, PHP and .NET workers use thin SDKs that talk to the SDK gateway of a self-hosted JoobQUI (/api/v1/sdk) with the server’s SDK token: they long-poll for tasks, renew their leases and complete or fail them with a stack trace, and never connect to Redis. Jobs are Core; SDK workflows need a JoobQ Pro key on the server.

Registry packages: on the roadmap. The 8 SDKs are not published to package registries yet. Copy sdks/<language> from the joobqui repository into your project and reference it by path.

Install guide for every language
shard.yml · terminalNative shard
dependencies:
  # Queues and jobs (MIT)
  joobq:
    github: azutoolkit/joobq
    version: "= 0.5.6"

  # Or durable workflows, with JoobQ Pro (needs read access to the repository)
  # joobq_pro:
  #   github: azutoolkit/joobq-pro
  #   version: "= 0.4.1"
shards install

# src/worker.cr
#   require "joobq"         # or: require "joobq_pro"

JoobQ is a shard; JoobQ Pro (workflows) is a commercial shard in a private repository and brings the joobq revision it was tested with, so list one or the other.

Data flow

SDK workers talk to the gateway, never to Redis

Your network

Your SDK workers

Python · TypeScript · Ruby · Go · Rust · Java · PHP · .NET

PyTSRbGoRsJvPhp.N

Operators

Browser · console at /ui/

joobqui-selfhosted · one or more instances

JoobQUI server

  • SDK gateway/api/v1/sdk
  • Console API/api/v1
  • Workflow engineconducts SDK runs · Pro

Only outbound call: licence check-in every 15 min → app.joobq.io

Redis 6.2+

queues · leases · workflow histories

PostgreSQL

accounts · token hashes · audit

Your Crystal workers

Crjoobq + joobq_pro shards

The gateway holds the one implementation of retries, dead letters, leases and delays, so every language gets the same rules, and enqueues and starts are audited. More throughput comes from more server instances.

Workflows · JoobQ Pro

Durable workflows that replay, not just retry.

A workflow is a declared graph of steps. Every state change is an event appended to its history in Redis by one Lua script, so a crashed worker loses nothing Redis kept. Crystal workflows run on the engine directly; workflows written with the 8 SDKs are conducted by the same engine on the server, which sends each step to a worker as its own leased task.

Fire-and-forget job

JoobQ · OSS
  1. enqueue
  2. perform
  3. retry · backoff
  4. dead letter

A job is one unit of work: it is retried with exponential backoff, then kept in the dead-letter set with its error. Undoing what earlier jobs already did is left to your code.

Durable workflow

JoobQ Pro
  1. reserve
  2. charge
  3. release

A workflow is a declared graph whose state is a fold of an append-only history in Redis. The engine decides every step, so a crashed worker loses nothing Redis kept.

  • Saga compensation on failureA step that fails for good runs the compensations of the completed steps, newest first; then the run is failed.
  • Signals with timeoutswait_for parks the run without holding a worker; with no signal in time the engine records StepTimedOut.
  • Deterministic replayreplay(history, definition) re-decides a recorded history against new code and reports the first divergence.
Read the workflow guide

Simulate execution

runconf-signal-python-7d2econf-signal-pythonpending
  1. step before
    step · activitypending
  2. wait_for approval
    wait_for signal: "approve" · 60 spending
  3. step after
    input: steps.approval.output.bypending

The run parks on wait_for "approval" without holding a worker, until an operator sends the approve signal.

Event history

  1. No events yet. Press Simulate execution.

Audit log preview

append-only
Audit rows written by the simulated calls, newest first
Rows appear when an operator calls the API: the signal, a re-drive.

A deterministic replay of the conformance workflows, in your browser. Nothing is sent anywhere.

JoobQUI console

The operator console your on-call team will actually open.

JoobQUI runs next to your workers and reads the same Redis. The frame below copies the self-hosted console, page for page, with sample numbers: the re-drive, the signal and the audit log work.

https://queues.example.com/ui//ui/workflows/conf-signal-python-7d2e/ui/dlq/ui/audit
Sample data

Overview

Live health of workflows, queues and workers.

  • Active workflows
    8up1
  • Jobs/s
    103.9up15.6
  • Failed / DLQ
    13up2
  • Worker nodes
    5
  • p99
    280msdown31ms

Throughput

Completed jobs per second

Latency

Time from start to finish

Queues

93 waiting · 22 running

  • default payments checkout-api
    22 waiting · 5/8 busy
  • emails growth notifier
    33 waiting · 6/10 busy
  • billing payments billing-worker
    2 waiting · 4/8 busy
  • conf-python conformance-python
    0 waiting · 1/4 busy
  • reports growth notifier
    Paused31 waiting · 0/8 busy
  • webhooks payments checkout-api
    5 waiting · 6/12 busy

Quick actions

Also available from ⌘K

/ui/

Throughput and latency, as it happens

The overview listens to a WebSocket stream of lifecycle events and metric ticks: throughput, p50 / p95 / p99 latency, every queue’s backlog and busy workers, from 1 minute to 7 days.

  • Live stream

    The header says Live while the stream is open, and when it drops.

  • Latency percentiles

    p50, p95 and p99 from the run-time histogram JoobQ keeps in Redis; per queue too, with a JoobQ Pro key.

  • Quick actions

    Drain or resume every queue at once, operators and admins only; viewers see them disabled.

/ui/workflows/conf-signal-python-7d2e

Each run as a graph, with its full history

With a JoobQ Pro key on the server: every step of a run, its compensations and its event history. Operators signal, cancel, terminate or re-drive a run, and every one of those calls is audited.

  • Saga compensation

    A step that fails for good undoes the completed ones, newest first.

  • Signals with timeouts

    wait_for parks the run without holding a worker until the signal or the timeout.

  • Try it

    Run the simulation: send the approve signal, or watch release compensate a failed charge.

/ui/dlq

Dead letters, triaged in bulk

Every dead letter with its error class and message; open one for its stack trace and the stored job, secret-looking values masked. Re-drive one, or select many and re-drive or purge them at once.

  • NonRetryableError

    A job that raises it skips its remaining retries and goes straight to the dead letters.

  • Outcome per job

    The answer counts what was re-driven and what was skipped: already gone, or unreadable.

  • Try it

    Re-drive the selected rows, or open a job and re-drive it: the Audit view gets the row.

/ui/audit

Access control an auditor can read

viewer, operator and admin enforced by the server on every route; OpenID Connect single sign-on, TOTP two-factor, admin-issued API tokens, and an audit row for every change and every sign-in.

  • Critical changes first

    Token, role and second-factor changes write the audit row before they act.

  • Denied is recorded too

    A viewer’s refused purge is a row, with the address it came from.

  • Export

    CSV or JSON, filtered by actor, action, outcome and date.

Comparison

What each part of the ecosystem gives you.

JoobQ Pro builds on the open-source core; JoobQUI operates both and runs the SDK gateway. The JoobQUI column says what the self-hosted server and its console add; a feature marked Pro there needs a JoobQ Pro key on the server.

What JoobQ, JoobQ Pro and JoobQUI each include
Capability
JoobQ
Open source (MIT)
JoobQ Pro
Commercial shard, Pro key
JoobQUI
Self-hosted, licensed
At a glance
Self-hostingIn your process, on your RedisIn your process, on your RedisYour servers, Docker Compose3
Polyglot workersCrystalCrystal+ 8 SDK languages via /api/v1/sdk
Native sagas and signalsNot includedIncludedInspect, signal, cancel, re-drive1
Encrypted payloads (AES-256-GCM)encrypted_propertyIncludedSDK encrypted_fields; shown as [encrypted]
RBAC, SSO and audit logNot includedNot included3 roles · OIDC · TOTP · audit2
LicensingMIT, freeIncluded with a paid licence1Flat monthly tiers, cancel any time
Queues and jobs
Typed jobs, Redis queues, per-queue workersIncludedIncludedPause, resume, clear, resize
Retries with exponential backoffIncludedIncludedRetry and delete jobs
Dead-letter set and redriveIncludedIncludedBulk redrive and purge
Delayed, recurring and cron jobsIncludedIncludedPause, resume, run now
Queue throttling (per queue, at claim)IncludedIncludedSDK queues the server’s JoobQ config defines
HTTP management APIBearer tokens, no OpenAPI fileSame as JoobQOpenAPI 3.1, /api/v1
Job expiryIncludedIncludedNot included
Batch enqueueNot includedNot includedSDK enqueue_many, 1 to 500 jobs
Batches with completion callbacksNot includedpartialCrystal onlyNot included
Unique jobsNot includedIncludedSDKs: while_locked; the release modes need Pro
Rate limiting (per key, across processes)Not includedIncludedSDK rate_limit1
Run timeoutsNot includedIncludedNot included
Durable workflows
Event-sourced history in RedisNot includedIncludedEvent history, time travel
Workflows written with the 8 SDKsNot includedThe engine conducts themThrough the gateway1
Sagas: compensation newest firstNot includedIncludedCancel with compensation
Signals, queries, timers, child workflowsNot includedIncludedSignal, query
Validated updatesNot includedpartialCrystal; SDKs comingSend updates
Deterministic replay and migrationNot includedIncludedReplay, migrate (dry run)
Continue-as-newNot includedIncludedContinue a run now
Cancellation scopesNot includedpartialCrystal; SDKs comingCancel one scope
Worker build idsNot includedpartialCrystal workersPromote, retire, re-pin
Search attributes and workflow schedulesNot includedIncludedFilter runs, manage schedules
Bulk operations with dry runNot includedNot includedUp to 200 ids or a filter1
Operations and security
Latency percentiles (p50 / p95 / p99)partialHistogram in RedisIncludedLive charts, 1 min to 7 days1
Alert rulesNot includedIncludedRules, acknowledgement1
Email, Slack, PagerDuty and signed webhook channelsNot includedNot includedThey deliver Pro alerts
Prometheus metrics endpointNot includedNot included/metrics
Roles, API tokens and audit logNot includedNot includedviewer · operator · admin
TOTP two-factor and OIDC single sign-onNot includedNot includedTOTP; SSO2
Secret-looking payload keys maskedNot includedHistory archive redactionEvery view and export
  1. 1Needs a JoobQ Pro key on the server. Every paid self-hosted licence includes one; a 14-day trial key is available once per organization.
  2. 2Single sign-on is in the Team and Enterprise tiers.
  3. 3The server checks in with the licence portal every 15 minutes (version, active users, worker count, the Pro features in use, an instance id). Jobs, payloads and accounts stay in your Redis and PostgreSQL.

Pricing

Free to start, licensed when you run the console.

JoobQ is open source and free. A paid tier licenses the self-hosted JoobQUI server for your deployments, and every one of them includes JoobQ Pro: there is no separate Pro price.

  • Free Forever

    JoobQ Open Source · MIT

    $0

    JoobQ, the open-source core, in Crystal. MIT licensed, no key, no limits we enforce.

    Licence
    MIT
    Key
    None
    Limits
    None
    • Typed jobs, queues, retries and dead letters
    • Delayed, recurring and cron jobs
    • Encrypted job properties
    • A REST management API (off by default)
    • Community support on GitHub
    Get Started
  • Starter

    JoobQUI Self-Hosted + JoobQ Pro

    $49/ month

    One self-hosted console for a small team.

    Seats
    5
    Deployments
    1
    SSO
    No
    • Everything in Free
    • Self-hosted JoobQUI: 5 seats, 1 deployment
    • The SDK gateway: workers in 8 more languages
    • A JoobQ Pro key, renewed with each licence check-in
    • Live KPIs, workflows, alerts, dead-letter triage
    • Roles, API tokens, audit log, TOTP
    Get Starter
  • Team

    Recommended

    JoobQUI Self-Hosted + JoobQ Pro

    $199/ month

    Up to 3 deployments and single sign-on.

    Seats
    25
    Deployments
    3
    SSO
    OIDC
    • Everything in Starter
    • 25 seats, 3 deployments
    • OpenID Connect single sign-on (PKCE)
    • SSO group-to-role mapping
    Get Team
  • Enterprise

    JoobQUI Self-Hosted + JoobQ Pro

    Contact us

    Unlimited seats for organisations with many operators.

    Seats
    Unlimited
    Deployments
    10
    SSO
    OIDC
    • Everything in Team
    • Unlimited seats, 10 deployments
    • Terms agreed with you
    Contact sales

Transparent licence terms

  • Monthly, billed through Stripe; taxes added at checkout where they apply.
  • No key to paste: each server connects itself with Sign in with JoobQ and fetches its licence.
  • Seats, deployments and SSO are the limits the licence enforces, nothing hidden.
  • Cancel any time: the licence runs to the end of the paid month.
  • An unreachable portal does not end a paid period for up to 7 days after the last check-in.
  • A 14-day JoobQ Pro trial key, once per organization, from the portal.

Enterprise security & sovereignty

Runs in your network, answers to your auditors.

  • Your network, your data

    Jobs, workflow histories and payloads stay in your Redis; accounts and the audit trail in your PostgreSQL. Only the licence check-in leaves.

  • Workers keep running

    If a licence lapses, the console’s operations stop until you renew, but the SDK gateway keeps serving: workers go on running jobs and workflows.

  • Keys you hold

    Fields sealed with AES-256-GCM under JOOBQUI_PAYLOAD_KEYS; the console shows them as [encrypted].

  • Least privilege

    viewer, operator and admin on every route, OIDC single sign-on, TOTP two-factor, an audit row for every change.

FAQ

Questions operators ask first.

What Redis do I need?

One Redis server, version 6.2 or newer (the SDK gateway claims tasks with LMOVE), reachable by your Crystal workers and the JoobQUI server (SDK workers never connect to it: they talk to the server over HTTPS). Connect with REDIS_URL as redis://, rediss:// or a unix socket; ACL users are supported. Over TLS, JoobQUI checks the certificate chain (REDIS_CA_FILE names your own authority) but not the host name.

Redis Cluster is not supported: keys are not hash-tagged. If losing the last second of workflow history on a crash is not acceptable, run Redis with AOF appendfsync always. Use a noeviction (or volatile-*) policy so the console never forgets a session revocation.

Where does my data live with the self-hosted console?

In your infrastructure. Jobs, workflow histories and live events stay in your Redis; accounts, API token hashes, the audit log and notification channels go to your PostgreSQL.

The only traffic to us is the licence check-in, every 15 minutes: the server’s address, its version, the number of active accounts, the number of workers, which Pro features are in use and an instance id. Payload values whose keys look secret are masked in every view and export, and fields sealed with encrypted_property are shown as [encrypted]: the console holds no key to open them.

Can I write workers in languages other than Crystal?

Yes, in 8 more: Python, TypeScript, Ruby, Go, Rust, Java, PHP and .NET. Each SDK is a small client of the SDK gateway (/api/v1/sdk) of a self-hosted JoobQUI server: it registers the worker, long-polls for tasks, renews their leases and completes or fails them with a structured stack trace. Workers never connect to Redis. Jobs are Core; workflows need a JoobQ Pro key on the server, whose engine conducts them step by step.

Crystal stays first-class: the JoobQ and JoobQ Pro shards run jobs and workflows natively, without the gateway. The SDKs are not on package registries yet; copy sdks/<language> from the joobqui repository and reference it by path. Every language is tested against a real server.

How does JoobQ fit with Crystal and Azu?

JoobQ is a plain shard: require "joobq", define jobs as structs and start workers with JoobQ.forge. It works in any Crystal program; Crystal 1.22 or newer is required.

For Azu apps, the Azu CLI generates the JoobQ setup (azu generate joobq) and runs workers (azu jobs:worker); the JoobQUI console is itself an Azu application.

What happens if the console cannot reach the license service?

The server checks in every 15 minutes. If the license service cannot be reached, the last good license stays in force for up to 7 days after the server’s last successful check-in, as long as its paid-until date has not passed. A server that has not checked in once since it started gets no such grace.

After that, or when the license is expired, unpaid or disabled, the console’s operations routes of /api/v1 and /metrics answer 402 paid_license_required; sign-in and account routes keep working, and so does the SDK gateway (/api/v1/sdk/*), so workers keep running jobs. ./joobqui license:refresh checks in on demand.

How fast is it?

Throughput depends on payload size, TLS, Redis persistence and what your jobs do, so we publish no headline number. JoobQ Pro ships its benchmark harness (benchmarks/ in joobq-pro) and joobqui one for the SDK gateway (bench/sdk-gateway/). Measure completed jobs with your own workload.

Are jobs and activities exactly-once?

No. JoobQ delivers at least once: after a crash or redelivery a job, or a workflow activity, can run again. Each workflow attempt starts at most once, and ctx.dedupe_key gives activities a stable key to pass to services that support idempotency.