Architecture overview
Components at a glance#
Abrq DIP is a small set of long-running services around two data stores:
| Component | Role |
|---|---|
| Frontend | nginx serving the single-page web UI |
| API | FastAPI application served by Gunicorn with Uvicorn workers; every REST endpoint lives under /api/v1 |
| Workers | Celery workers that execute pipeline runs and maintenance tasks |
| Beat | A single Celery Beat scheduler that enqueues all periodic work |
| Migrator | A one-shot process that applies database migrations under an advisory lock, then exits |
| PostgreSQL | The framework database (platform metadata) plus a separate datastore database (landing area) |
| Redis | Celery broker and result backend, dedup cache, and rate-limit storage |
All four backend roles (API, worker, beat, migrator) run from one backend container image; an entrypoint argument selects the process kind. See Components for per-component detail and Background processing for the worker and scheduler model.
Control path#
The control path is how operators and the platform's own metadata move:
- The browser loads the SPA from the frontend and calls the API. On
Kubernetes, the ingress routes
/apito the API service and everything else to the frontend; in Docker Compose, the frontend's nginx proxies/api/, the SSE log streams, and/metricsto the backend container. - The API reads and writes only the framework database and Redis. Connector credentials and other secrets are encrypted with the master key before they touch the database, and are decrypted only at the moment a connection is opened.
- With runs mode set to
celery(the default in the shipped deployment configurations), the API never executes pipeline work itself — it enqueues runs onto Redis queues for the workers.
Data path#
Pipeline data does not pass through the frontend. The executing process — a
Celery worker, or the API process itself when runs mode is sync — connects
directly to the configured source and destination systems and moves data
between them:
- CDC changes land in mirror tables on a relational destination.
- Stream batches are staged durably, then fanned out to each configured destination independently; a batch is released only after every enabled destination has durably accepted it (or dead-lettered it).
- File-ingestion and email-feed payloads load into relational destination tables.
- SQL tasks read from and write to the engines bound to their environment.
The framework database keeps metadata, run history, and logs; ingested data lands in the destinations you configure. The separate datastore database is a bundled landing area used for CDC mirror tables and file-ingestion landings.
From source to destination#
A typical scheduled run flows like this:
- Trigger. The Beat scheduler fires a periodic tick (a job schedule, a CDC sync, an inbox or file poll), or a user starts a run from the UI.
- Enqueue. With
ABRQ_RUNS_MODE=celery, the API enqueues the run onto its family-specific Redis queue; withsync, it executes inline. - Execute. A worker picks the task up and opens connections to the source and destination using the stored connector definitions.
- Apply policy. The observed source schema is compared against the schema registry, and any drift is handled by the pipeline's policy — Reject, Evolve, or Rescue. See Schema drift policies.
- Write. Rows are written to the destination — a mirror table, a warehouse table, a Kafka topic, or objects in a bucket.
- Record. Run status, logs, and metrics are recorded in the framework database; notifications and alert rules fire according to configuration.
What is stored where#
| Store | Contents |
|---|---|
| Framework database | Connectors, pipelines, projects and tasks, users and RBAC, encrypted secrets, run history and logs, the audit chain, staged stream batches |
| Datastore database | CDC mirror tables and file-ingestion landings |
| Redis | Broker queues, task results, dedup cache, rate-limit counters |
| Beat schedule file | /var/abrq-dip/celerybeat-schedule on a persistent volume, so the scheduler resumes where it left off |