Architecture and deployment
The processes of a self-hosted deployment and what each one talks to. Only the server reaches the portal, and only to renew its licence and Pro key.
Processes
| Process | Command | What it does |
|---|---|---|
| Web | joobqui-selfhosted | The console's API (/api/v1) and static files (/ui/), the SDK gateway (/api/v1/sdk), the live stream, the schedule runner, retention, alert rules and notifications (with a Pro key), the licence heartbeat. Applies the database migrations at start. With a Pro key it also conducts the SDK workflows. |
| Queue worker | joobqui-selfhosted --worker | JoobQ's queue workers for the Crystal job classes the server defines, and the schedule runner. Serves no HTTP. |
| Your SDK workers | your own process | Register job and workflow handlers and long-poll the gateway with JOOBQUI_SDK_TOKEN. |
| Your Crystal workers | your own process | Run JoobQ jobs and JoobQ Pro workflows against the same Redis. |
The command-line tasks (accounts:create, license:status, doctor, ...) run instead of the server: see Command line.
What lives where
- PostgreSQL (
DATABASE_URL) holds what must survive: accounts, recovery codes, API tokens (only their SHA-256 hashes), the audit trail, notification channels (their URLs and keys sealed withJOOBQUI_SECRETS_KEY) and the migration history. - Redis holds the working state: queues, delayed and running jobs, dead letters, counters, the worker registry, workflow histories, SDK leases and waits, session revocations, throttles, invites, schedule state and leader leases. Nothing in Redis is the only copy of an account, a token or the audit trail.
Redis 6.2 or newer is required. Use a noeviction or volatile-* policy (the bundled Compose file runs Redis with --appendonly yes and --maxmemory-policy noeviction). Sentinel and Cluster are not supported.
Several instances
Run more joobqui-selfhosted instances behind a load balancer for more workers or more console users. Their state is in Redis and PostgreSQL: sessions are signed cookies, SDK leases and waits are claimed atomically by whichever instance gets there first, and the work that must run once (alert notifications, audit purge) takes a leader lease. No sticky sessions are needed. Per instance: the telemetry history, the request counters of /metrics and the state of alerts (an acknowledgement sent to another instance answers 404). See Workers and instances.
Why the SDKs talk to a gateway
Direct Redis access for the SDKs was considered and declined: the rules for retries, dead letters, leases and delayed jobs have one implementation, the workflow rules another (the joobq-pro engine's); joobq-pro's storage format stays private; workers never hold the Redis credentials or the sealing keys; enqueues and starts are audited and queue pauses and concurrency limits apply. More throughput comes from more server instances, not a separate gateway image.
Deployment model
You run one product: the self-hosted server, joobqui-selfhosted (./joobqui inside its container image). It serves the console, its API and the SDK gateway behind the deployment licence gate, and keeps accounts in your PostgreSQL. This site documents it.