Skip to content
ABRQ DATADocs Abrq DIP · latest
Product page Request a trial
On this page

Components

Process model#

All backend roles run from a single container image. The image entrypoint dispatches on its first argument (or the ABRQ_PROCESS_KIND environment variable when no argument is given); any further arguments are passed through to the underlying command.

Kind What it runs
api Gunicorn supervising Uvicorn workers, bound to 0.0.0.0:8000
worker A Celery worker consuming every task queue by default
beat Celery Beat with a persistent schedule file — run exactly one replica
migrator Waits for the database, applies migrations under an advisory lock, exits

Ports#

Service Port Notes
API 8000 HTTP; also serves /health, /metrics, /docs, /openapi.json
Frontend 80 (container) Docker Compose publishes host port 8080 by default (ABRQ_FRONTEND_PORT)
PostgreSQL 5432 Internal only; not published in the production Compose files
Redis 6379 Internal only; not published in the production Compose files
Workers / Beat No listening ports

API#

The API is the FastAPI application served by Gunicorn with Uvicorn workers. The worker-process count defaults to 2 and is tuned with ABRQ_GUNICORN_WORKERS; the server uses a 30-second graceful shutdown timeout and a 60-second request timeout. Every REST route lives under /api/v1; two log streams are Server-Sent Events endpoints.

Frontend#

The frontend is an nginx container serving the built single-page application. In Docker Compose it also proxies /api/, the SSE routes, and /metrics to the backend container; on Kubernetes that split is the ingress's job (the chart routes /api to the API service first, then / to the frontend). The frontend serves its own lightweight /health location for container checks.

Workers, Beat, and the migrator#

  • Workers execute pipeline runs and maintenance tasks from Redis queues. They expose no ports and scale horizontally. Queue layout, concurrency, and shutdown behaviour are covered in Background processing.
  • Beat is the single scheduler process. It only enqueues periodic work — workers do the executing — and must never be scaled beyond one replica. See Background processing for the singleton rationale.
  • The migrator brings the framework database schema to the current head before the other components start. See Database migrations below.

Health probes#

Note. GET /health is the only health endpoint. There is no /ready, /healthz, or /livez — point liveness and readiness probes at the same path.

GET /health is a combined liveness and readiness check: it runs SELECT 1 against the framework database and pings Redis, returning 200 when both dependencies are healthy and 503 otherwise, with a body of {status, version, commit, deps}. It is exempt from authentication and from license enforcement, so it keeps answering even when the license has expired.

Default probe wiring in the Helm chart:

Component Probe Default
API Liveness GET /health on 8000 — initial delay 30 s, period 15 s
API Readiness GET /health on 8000 — initial delay 5 s, period 5 s
Worker Liveness + readiness exec celery -A abrq_dip.workers.celery_app inspect ping — initial delay 30 s, period 30 s, timeout 10 s (probe timeout is the configured value plus 5)
Beat No probes

The backend image additionally declares a Docker HEALTHCHECK that curls /health, which is what docker compose ps reports.

Images#

Image Base Notes
abrq-dip-backend python:3.12-slim, three-stage build Runs as non-root uid 1000 under tini; exposes 8000; one image for api, worker, beat, and migrator; release builds compile the core licensing/crypto modules and embed a signed integrity manifest
abrq-dip-frontend node:20-alpine build stage, served by nginx:1.27-alpine Exposes 80

The Helm chart defaults to these repository names with the latest tag; production installs should pin an explicit version tag.

Database migrations (advisory lock)#

The migrator waits for the framework database to accept connections (retrying for roughly five minutes), takes PostgreSQL advisory lock 49155, runs alembic upgrade head, then releases the lock and exits.

Because the lock serialises concurrent runners, the migration step is safe to run from every replica:

  • Kubernetes (default): migrator.initContainer: true runs the migrator as an init container on every API, worker, and beat pod. Exactly one init container applies the migrations while the rest block on the lock and then observe that head is already applied.
  • Kubernetes (external database only): migrator.enabled: true switches to a pre-install/pre-upgrade Helm hook Job instead. Leave it off with the bundled in-cluster PostgreSQL — the hook runs before the database subchart exists on first install.
  • Docker Compose: the production Compose files run a dedicated one-shot migrator service before the long-running services start.