Skip to main content

Data Flow

This page describes how data moves between AIQLick's services, covering API communication, database access patterns, real-time streaming connections, and the billing pipeline.

Frontend to Backend

The frontend communicates with the backend exclusively through GraphQL over HTTP and WebSocket.

  • Protocol: GraphQL queries and mutations over HTTPS (POST /graphql); subscriptions over WebSocket using the graphql-ws protocol.
  • Authentication: JWT token sent in the Authorization: Bearer {token} header. Tokens are stored in localStorage on the client.
  • File uploads: Multipart/form-data via a custom upload link that bypasses retry logic to avoid re-uploading on timeout.
  • Timeout: 90 seconds per operation (APOLLO_TIMEOUT).
  • Caching: Default fetch policy is cache-and-network.
  • Error handling: Authentication failures (401, UNAUTHENTICATED) trigger an automatic redirect to /auth/signin.

Frontend to Background Tasks

The frontend connects directly to background-tasks for AI operations, bypassing the backend entirely. This is configured through separate environment variables:

  • NEXT_PUBLIC_API_URL -- backend HTTP endpoint, also used for AI gateway HTTP (queryAi/mutateAi) and voice WS.
  • NEXT_PUBLIC_GRAPHQL_WS_URL -- backend WS endpoint, also used for AI streaming (subscribeAi).
  • Auth: The same JWT token is passed via the Authorization header on HTTP and via connectionParams on the WebSocket connection. AI traffic flows through the NestJS AI gateway, which mints a separate internal-service JWT for the upstream call to background-tasks; the frontend never sees that token.

Streaming Subscriptions

AI operations stream typed progress events back to the frontend in real time:

SubscriptionPurpose
cvExtractionCV parsing with structured data extraction
faceExtractionFace detection from CV documents
jobParsingJob description analysis
candidateJobMatching / userJobMatchingLive matching score calculation
agentChatStreaming AI agent responses (emits ChatProcessing, ChatContextLoaded, ChatChunk, ChatToolCall, ChatToolResult, ChatComplete, ChatError)
meetingInsightAI-generated meeting analysis
textRewriteAI text rewriting

Backend and Background Tasks (Shared Database)

The backend and background-tasks share the same PostgreSQL database instance per environment. This is the primary integration point between the two services.

  • Schema ownership: The Prisma schema in aiqlick-backend/prisma/schema.prisma is the single source of truth (135 models). All migrations and schema changes originate here.
  • Backend access: Uses Prisma 6 ORM with full type safety and relation loading.
  • Background-tasks access: Uses raw AsyncPG queries against the same tables. There is no ORM layer; SQL is written directly.
  • Coordination: Both services read and write to shared tables. For example, the backend creates Meeting records while background-tasks writes Transcription rows and MeetingInsight analysis for the same meeting.
  • Event signaling: Redis pub/sub is used for real-time coordination when database polling is insufficient.

There are no direct API calls between the backend and background-tasks. All data sharing happens through the database and Redis.

Jigasi to Background Tasks

The custom Jigasi fork streams audio from Jitsi meetings to background-tasks for real-time transcription.

  • Transport: WebSocket connection to wss://ai.aiqlick.com/transcription/ws.
  • Audio format: Binary PCM frames (16kHz, 16-bit, mono).
  • Processing: Background-tasks forwards the audio to AWS Transcribe for speech-to-text conversion and writes Transcription records to the database.
  • Result delivery: Transcription segments are stored in PostgreSQL and available to the frontend through GraphQL queries.

Jitsi Events to Background Tasks

Prosody (the XMPP server in the Jitsi stack) sends webhook notifications to background-tasks when meeting lifecycle events occur.

  • Endpoints: POST /api/events/room/created and POST /api/events/room/destroyed
  • Events: Room creation, participant join/leave, room destruction.
  • Trigger: When a meeting ends, background-tasks automatically generates a MeetingInsight from the accumulated transcription data using AWS Bedrock.

Billing Data Flow

Credit-based billing spans both the backend and background-tasks:

  • The backend handles Stripe webhook events (subscription changes, pack purchases, refunds) and adjusts credit balances accordingly. Plan limits are enforced by the @CheckPlanLimit guard.
  • Background-tasks checks credit availability before each AI operation (BillingGate.pre_check()) and deducts credits after completion (BillingGate.check_and_consume()). Every operation is logged to AIOperationLog with token counts and credit cost.
  • Credit routing depends on the user's current mode: EMPLOYER with a selectedCompanyId charges the company balance; JOB_SEEKER mode charges the personal user balance.
  • Credit transfers: Pack purchases land in the user's personal balance. Billing owners transfer credits to company balances via the transferCredits mutation.
  • Enterprise (POSTPAID): For enterprise companies, the BillingGate bypasses credit checks and logs usage to AIOperationLog without deduction. A monthly cron generates Stripe invoices from aggregated usage. Overdue invoices block platform access until paid.