Skip to main content
Causeloop is a multi-tenant SaaS platform. This page describes the major components, how a request flows through them, and how tenant data stays isolated at every layer.

High-level components


Component descriptions

Frontend — Next.js (app.causeloop.ai)

The product UI is a Next.js application authenticated by Clerk. After exchanging the Clerk session for a platform JWT, the frontend communicates exclusively with the backend API and a WebSocket for realtime updates. Key routes:
Route groupPurpose
/(auth)/loginSign-in page (Clerk-powered)
/(onboarding)/onboardingPost-signup onboarding wizard
/(platform)/dashboardMain workspace dashboard
/(platform)/issuesIssue list and detail
/(platform)/patternsPattern list and detail
/(platform)/predictionsRisk signals and forecast
/(platform)/recommendationsRanked fix queue
/(platform)/integrationsConnector management
/(platform)/reportsGenerated reports
/(platform)/settingsWorkspace and member settings

Backend API — FastAPI (api.causeloop.ai)

The backend is a FastAPI application serving all product functionality under /v1. It is stateless and horizontally scalable. Key responsibilities:
  • Auth token issuance and verification
  • Business logic for issues, patterns, predictions, recommendations, clusters, and connectors
  • AI orchestration (dispatching analysis jobs to the LLM Router)
  • Tenant isolation via database RLS
  • Async job coordination via Kafka stubs (Celery-based workers in production)
  • Rate limiting (1,000 requests per minute per tenant by default)
Stack:
LayerTechnology
RuntimePython 3.11+
FrameworkFastAPI 0.115+
ValidationPydantic v2
AuthPyJWT (HS256 platform tokens), python-jose (RS256 Clerk verification)
MiddlewareRate limiting, Idempotency-Key support
DeploymentDocker, Railway, Render

LLM Router — AI providers

The LLM Router dispatches AI analysis tasks (root-cause analysis, pattern detection confidence scoring, recommendation generation) to the configured provider. Providers are tried in order:
  1. Anthropic — Claude models (ANTHROPIC_API_KEY)
  2. OpenAI — GPT-4o / GPT-4o-mini (OPENAI_API_KEY)
  3. Mock — Deterministic offline fallback (no keys required)
If both ANTHROPIC_API_KEY and OPENAI_API_KEY are absent, the API falls back to the mock provider automatically. Analysis results are plausible but not real.

Database — PostgreSQL with Row-Level Security

All product data lives in PostgreSQL 16. Multi-tenancy is enforced at the database layer using Row-Level Security (RLS):
  • Every tenant table has a workspace_id column.
  • Before executing any query, the API binds app.current_workspace_id on the session.
  • RLS policies reject reads and writes that do not match the bound workspace ID.
  • The application role (causeloop_app) does not have BYPASSRLS; a superuser role is kept separate for migrations only.
This means even a bug in the application layer cannot leak one tenant’s data to another.

Connectors and Ingestion

Connectors pull issues into a workspace from external tools. They operate in two modes:
  • Poll — the backend fetches issues from the external API on a configurable schedule (poll_interval_seconds).
  • Webhook (inbound push) — the external tool POSTs events to POST /ingest/{connector_token}, verified by HMAC signature.
Sync runs are tracked with start/end timestamps, record counts, and error details, accessible via GET /connectors/{id}/sync-runs.

WebSocket Gateway — Realtime channel

The backend exposes a WebSocket endpoint at /v1/stream. Authenticated clients connect with their platform JWT as a query parameter (?token=<jwt>). The gateway pushes typed event envelopes to all sockets belonging to the same tenant:
{"type": "issue.updated", "data": {"id": "iss_01J...", "status": "mitigating"}}
Event types that reach the browser: activity.created, issue.updated, pattern.updated, prediction.alert, recommendation.created, and job.updated (for async job progress).

Request and auth flow

1

User signs in via Clerk

The Next.js frontend delegates authentication to Clerk. On success, Clerk issues a signed RS256 session JWT to the browser.
2

Exchange for a platform token

The frontend calls POST /v1/auth/exchange with the Clerk session JWT. The backend verifies the JWT against Clerk’s JWKS endpoint (RS256), looks up or creates the user record, and issues a short-lived HS256 Bearer token bound to the user’s workspace.
3

API calls with Bearer token

All subsequent requests include the Bearer token in the Authorization header. Middleware resolves the token to {user_id, workspace_id, role, scopes} and binds the RLS session variable before any query runs.
4

Realtime updates via WebSocket

The frontend upgrades to a WebSocket connection at /v1/stream?token=<jwt>. The gateway verifies the token identically to the REST path, then pushes events for that tenant as they occur.

Deployment topology

In production, each logical layer runs as an independent set of replicas behind a load balancer:
ComponentReplicasNotes
Backend API2–8 (autoscale)Stateless; any replica handles any request
WS Gateway2–4Per-tenant fan-out; replicas share a Redis pub/sub bus
Kafka consumers (workers)1–4 per topic groupPattern detection, AI jobs, notification delivery
PostgreSQLPrimary + read replicaRLS enforced on all connections
For local development, docker-compose.yml runs the API, PostgreSQL, and Caddy (reverse proxy) as a single-box stack.

Quickstart

Sign in and see your first insights in 10 minutes.

Deploy & Security

Self-hosting, environment variables, and security controls.