Skip to content

Backend Deep Dive

Application structure

backend/app/main.py creates the FastAPI app, configures CORS and language middleware, seeds categories during lifespan, and registers auth, admin, chat, grievance, dashboard, file, and tracking routers.

The async stack is FastAPI + Uvicorn + SQLAlchemy/asyncpg. Configuration is loaded with pydantic-settings; database URLs support both local TCP and Cloud SQL socket overrides.

Router inventory

Router Representative responsibilities
auth Login, JWT creation, current-user resolution
admin User/category/knowledge-base administration
chat Session lifecycle, SSE messages, uploads, STT/TTS, RAG
grievances Case listing, details, status actions, assignment-facing APIs
dashboard Role-specific counts, workload, SLA metrics
files Attachment and ATR storage/download operations
tracking Natural-language status questions

The chat router demonstrates the request lifecycle particularly well: it authenticates, loads a user-owned session, delegates to handle_chat_turn, and wraps each yielded event as data: ...\n\n for browser SSE consumption.

Provider adapters

The backend isolates external systems behind modules such as app.files.storage, app.services.vector_store, app.chat.audio_service, and app.llm. This keeps route handlers focused on HTTP contracts and makes local MinIO/Redis/Postgres development possible while GCP services are the deployment target.

Configuration details

Settings cover Postgres credentials and pool sizing, LiteLLM endpoint/model, NVIDIA and Vertex options, Gemini embedding model/dimension, chunk sizing, allowed origins, Firebase/GCS identifiers, and seed-admin credentials. database_url_override is important for Cloud SQL Unix socket connection strings.

The defaults are useful for local boot but unsafe as production values: changeme database/password fields and placeholder API/JWT secrets must be replaced through environment variables or Secret Manager.

Async and consistency

FastAPI dependencies provide an AsyncSession; database operations use SQLAlchemy async queries. Redis session writes and PostgreSQL grievance finalization are separate consistency domains. If finalization succeeds in one and fails in the other, recovery behavior must be verified in handle_chat_turn and should be made idempotent around the session completion marker.

API lifecycle

Authenticated dependencies resolve the current user before chat, upload, RAG, and case operations. Chat returns text/event-stream; upload parsing and GCS storage are explicit steps. Errors become HTTP exceptions and are logged with structured messages.

Notable choices

  • Redis holds temporary conversational session state while PostgreSQL owns durable cases.
  • Cloud services are behind focused storage, audio, and vector-store modules.
  • Startup category seeding reduces first-run setup friction but can make boot depend on database availability.
  • Cloud Run migration, seed, and ingestion jobs separate operational work from request handling.

Interview answer

“The backend is an async modular monolith: routers expose role-aware APIs, services own workflow logic, SQLAlchemy owns durable records, Redis owns chat sessions, and provider adapters isolate GCS, Gemini, and audio services.”