Full Stack Python AI SaaS Platform — Django, FastAPI, Next.js, and Production RAG
This brief proposes a full stack Python AI SaaS platform architecture for long-term product development: Django and FastAPI backend services, a Next.js TypeScript frontend, production RAG pipelines with vector search, LangGraph agent workflows, and Docker-based deployment on AWS or GCP — designed so a senior developer can own delivery across the entire stack without coupling AI experiments to core product stability.
Proposed outcome: A modular SaaS stack where Django REST Framework handles auth, tenants, and billing; FastAPI owns streaming RAG and agents; Next.js delivers a Tailwind chat and document UI; and every LLM feature ships with Celery async jobs, Langfuse traces, tenant-isolated vectors, and CI eval gates.
Scenario
This is a proposed solution for a product team building or scaling an AI-powered SaaS application — matching the pattern of a senior full stack Python developer joining for long-term, contract-to-hire product work across backend, frontend, and AI integration.
- Product type: B2B SaaS with AI copilot, document Q&A, workflow automation, or semantic search as core differentiators
- Team shape: Remote-first; product managers and designers available; engineer owns architecture and implementation quality
- Delivery cadence: MVP in 8–12 weeks, then continuous sprints on RAG quality, agent features, and scale
- User base: Multi-tenant workspaces with role-based access, optional API keys, usage-metered AI features
- AI capabilities: Chat over uploaded documents, LangGraph automations, semantic search, multi-model routing (OpenAI, Claude, Gemini)
- Quality bar: Production-grade code — tests, observability, tenant isolation, and security on every AI endpoint
Problem
Teams hiring full stack Python + AI engineers often inherit a Django monolith with synchronous LLM calls in views, a disconnected React frontend, and RAG notebooks that never reach production. The result is slow chat, untestable prompts, and no path to scale ingestion or add agents safely.
- Monolith trap — LangChain logic embedded in Django views blocks workers and couples AI experiments to core deploys
- Frontend/backend drift — React and DRF serializers diverge; TypeScript types stale within sprints
- RAG without ops — vector indexes built once locally; no incremental updates, eval regression, or per-tenant filters
- Model vendor lock-in — hard-coded OpenAI calls with no fallback when latency, cost, or policy shifts
- Agent unpredictability — CrewAI demos without timeouts, checkpoints, and tracing fail under concurrent users
- Scale surprises — large file embedding on the request path; Celery queues unmonitored until backlog stalls ingestion
- Security gaps — LLM endpoints without rate limits; missing audit of which chunks were retrieved for which tenant
Requirements
Functional
- Core SaaS: User auth, organizations/workspaces, subscriptions, REST API (DRF), Django admin for ops
- AI chat / Q&A: RAG over tenant documents with streaming SSE responses and source citations
- Document ingestion: Upload → parse → chunk → embed → index; PDF, DOCX, HTML supported
- Agent workflows: LangGraph graphs — summarize, classify, route, notify — triggered via API or schedules
- Multi-model support: Router across OpenAI, Anthropic Claude, Google Gemini with per-task defaults
- Semantic search: Cross-document search API consumed by Next.js and external integrations
- Frontend: Next.js App Router, TypeScript, Tailwind — chat, document library, workspace settings
- Webhooks: Events on ingestion complete, agent run finished, usage thresholds
Non-functional
- Latency: Chat first token < 1.5 s p95; 10 MB document ingested async within 60 s
- Tenancy: Strict isolation — every query filters by
tenant_idin Postgres and vector metadata - Availability: 99.9% on API tier; graceful degradation when an LLM provider is down
- Security: JWT auth, encrypted secrets, rate limiting, CSP headers on Next.js
- Observability: Langfuse traces per LLM call; Sentry on application errors
- CI/CD: GitHub Actions — pytest, ruff, Docker build, deploy staging then production
Architecture
The proposed design splits product core (Django) from AI inference (FastAPI) while sharing PostgreSQL schema and JWT trust. Celery workers handle ingestion and long agent jobs; Next.js talks to both services through a BFF or direct API routes with shared auth cookies.
Platform architecture — Django owns SaaS core; FastAPI streams AI responses; Celery async pipeline feeds tenant-scoped vector indexes
Ingestion and chat sequence — uploads return immediately; RAG chat retrieves tenant-scoped chunks and streams with auditable citations
Component map by layer — frontend, core backend, AI services, async workers, and data stores
End-to-end flow
Product data path — AI features always run against tenant-filtered indexes; agent write actions emit webhooks for integrations
Service responsibility split — what lives in Django vs FastAPI vs Celery workers
Streaming chat latency budget — target first token under 1.5 s p95
Recommended stack
Recommendation: Django 5 + DRF for SaaS core, FastAPI for AI endpoints, Next.js + TypeScript + Tailwind for frontend, Celery + Redis for async, PostgreSQL + pgvector for tenant data and vectors, LangGraph for agents, LiteLLM for multi-provider routing, and Langfuse for observability — deployed via Docker on AWS ECS or GCP Cloud Run with GitHub Actions CI/CD.
| Layer | Technology | Why |
|---|---|---|
| Core backend | Django 5 + DRF | Mature auth, admin, ORM, migrations — fastest path to multi-tenant SaaS CRUD and billing hooks |
| AI backend | FastAPI | Native async, SSE streaming, OpenAPI — keeps LLM latency off Django request workers |
| Task queue | Celery + Redis | Proven Python async for ingestion, embedding batches, and long agent graphs |
| Frontend | Next.js 14+ App Router, TypeScript, Tailwind | SSR for marketing, client components for chat streaming; shared types via openapi-typescript |
| LLM router | LiteLLM | Single interface to OpenAI, Claude, Gemini; fallback chains and cost attribution per tenant |
| RAG / agents | LangGraph + LlamaIndex parsers | Graph checkpoints for agents; LlamaIndex loaders for document ingest consistency |
| Vector DB | pgvector → Pinecone | One DB early; dedicated ANN index when corpus or query volume grows |
| Primary DB | PostgreSQL | Users, tenants, document metadata, job status, usage metering |
| Cache / broker | Redis | Celery broker, rate limit counters, hot embedding cache |
| Observability | Langfuse + Sentry | LLM trace IDs linked to tenant; error monitoring on Django and FastAPI |
| Infra | Docker, AWS ECS or GCP Cloud Run, GitHub Actions | Container parity dev→prod; defer Kubernetes until traffic warrants it |
Why Django + FastAPI instead of FastAPI-only? Django admin, auth plugins, and ORM migrations save weeks on SaaS foundations. FastAPI-only teams often rebuild permissions, admin, and billing adapters from scratch.
Why LangGraph over CrewAI for production? Explicit graph edges, checkpoint resume, and unit-testable nodes beat autonomous multi-agent role-play for predictable SaaS features.
Why pgvector before Pinecone? Tenant metadata filters in SQL alongside vectors simplify isolation proofs; migrate when ANN p95 exceeds ~400 ms or corpus passes ~2M chunks.
Preferred AI stack summary: LiteLLM → LangGraph (agents) + LlamaIndex (ingest) + pgvector (retrieval) + Langfuse (evals/traces). OpenAI for default chat quality; Claude for long-context synthesis; Gemini as cost-optimized fallback.
Agent & component design
1 — Django DRF core API
- Models:
User,Tenant,Membership,Document,UsageRecord - Endpoints: Auth, workspace CRUD, document upload (S3 presigned), billing webhooks
- Output: JWT with
tenant_idclaims consumed by FastAPI - QA gate: pytest coverage on permissions — user A cannot read tenant B documents
2 — FastAPI AI gateway
from fastapi import FastAPI, Depends
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
app = FastAPI()
class ChatRequest(BaseModel):
message: str
conversation_id: str | None = None
@app.post("/chat/stream")
async def chat_stream(req: ChatRequest, tenant=Depends(verify_jwt)):
chunks = await retriever.search(req.message, tenant_id=tenant.id, top_k=8)
async def event_gen():
async for token in llm_router.stream(req.message, chunks):
yield f"data: {token}\n\n"
return StreamingResponse(event_gen(), media_type="text/event-stream")
3 — Celery ingestion worker
- Task:
ingest_document(doc_id, tenant_id)— idempotent; skips if hash unchanged - Steps: Download from S3 → LlamaIndex parse → chunk (512 tokens, 64 overlap) → embed → pgvector upsert
- QA gate: Ingest 50 fixture docs in CI; assert chunk count and tenant metadata on every vector
4 — LangGraph agent: document workflow
| Node | Input | Output |
|---|---|---|
classify | Document text | Category label + confidence |
summarize | Chunks | Executive summary (structured JSON) |
route | Category | Webhook target or human review flag |
notify | Summary + route | Email/Slack via integration API |
5 — LLM router (LiteLLM config pattern)
ROUTES = {
"chat": {"model": "gpt-4o-mini", "fallback": ["claude-3-5-haiku", "gemini-2.0-flash"]},
"summarize": {"model": "claude-sonnet-4", "fallback": ["gpt-4o"]},
"embed": {"model": "text-embedding-3-large", "fallback": []},
}
async def complete(task: str, messages: list, tenant_id: str):
route = ROUTES[task]
try:
return await litellm.acompletion(model=route["model"], messages=messages)
except Exception:
for fb in route["fallback"]:
return await litellm.acompletion(model=fb, messages=messages)
raise
6 — Next.js chat module
- Components:
ChatThread,CitationPanel,DocumentDropzone— Tailwind design tokens - Streaming: Native
EventSourceor Vercel AI SDK against FastAPI SSE - Types: Generated from FastAPI OpenAPI spec — no hand-maintained interfaces
7 — Eval runner (CI)
- Golden set: 50 tenant-scoped Q&A pairs with required citation doc IDs
- Gate: ≥85% citation recall; zero cross-tenant leakage in retrieval tests
- Tool: pytest + Langfuse dataset export on nightly schedule
Indicative model routing mix — cheap models for chat volume; larger models for summarization
MVP delivery curve — cumulative feature readiness across six implementation phases
Implementation plan
Phase 1 — SaaS foundation (week 1–3)
Django project with DRF, custom user + tenant models, JWT auth, S3 upload presigns, Next.js App Router shell with Tailwind, Docker Compose (Postgres, Redis, Django, FastAPI stub). GitHub repo with ruff, pytest, and pre-commit hooks.
Risk: Over-scoping admin UI — use Django admin for v1. Rollback: single-tenant mode flag for early dogfood.
Phase 2 — Ingestion + RAG (week 4–6)
Celery ingest pipeline, pgvector extension, embedding worker, FastAPI /chat/stream and /search, 30-case eval set in CI. Langfuse project wired for trace IDs.
Risk: PDF table extraction quality — add fallback OCR path for scanned docs. Rollback: text-only upload restriction until parser stable.
Phase 3 — Frontend product UX (week 7–9)
Document library, streaming chat with citation sidebar, workspace settings, loading/error states, responsive Tailwind layout. openapi-typescript generated hooks for DRF and FastAPI.
Risk: SSE through corporate proxies — add WebSocket fallback if needed. Rollback: non-streaming chat endpoint for blocked networks.
Phase 4 — Agents + multi-model (week 10–12)
LangGraph document workflow (classify → summarize → route), LiteLLM router with Claude and Gemini fallbacks, Celery trigger from DRF on ingest complete, agent status API for frontend polling.
Risk: Agent run timeouts — cap graph at 120 s with checkpoint resume. Rollback: disable agent auto-trigger; manual run only.
Phase 5 — Scale + observability (week 13–15)
Rate limiting per tenant, load test 200 concurrent chat sessions, GitHub Actions deploy to AWS ECS or Cloud Run, staging environment, Sentry alerts, Celery Flower or equivalent queue dashboard.
Risk: Cold start on serverless FastAPI — min instances > 0 in prod. Rollback: scale Django and FastAPI independently.
Phase 6 — Hardening (week 16–18)
Tenant isolation penetration test, secrets rotation runbook, API documentation publish, usage metering hooks for billing, Pinecone migration plan documented if pgvector p95 degrades.
Risk: Billing integration scope creep — ship usage export CSV before Stripe metered billing. Rollback: manual usage reports from UsageRecord table.
Reporting & ops
| Signal | Source | Cadence |
|---|---|---|
| RAG citation recall | pytest eval suite in CI | Every deploy (blocking) |
| Chat first-token p95 | Langfuse + APM | Real-time dashboard |
| Ingestion queue depth | Celery / Redis metrics | Alert if > 100 pending jobs |
| LLM cost per tenant | LiteLLM + Langfuse attribution | Weekly FinOps review |
| Provider fallback rate | Router logs | Weekly — tune model map |
| Application error rate | Sentry | Daily standup review |
| Cross-tenant leakage | Scheduled security test job | Weekly automated probe |
| Deploy frequency / rollback | GitHub Actions history | Per release |
Ops cadence would include weekly eval triage from Langfuse flagged traces, biweekly dependency and model version updates, and monthly review of vector index size versus pgvector→Pinecone migration triggers. A senior full stack engineer would own the runbook for Celery backlog recovery and LLM provider outage mode (fallback chain-only, read-only agents).
Proposed deliverables
Following the phased plan, a build would ship these artifacts:
- Django DRF monorepo — tenants, auth, documents metadata, usage metering, Django admin
- FastAPI AI service — streaming RAG chat, semantic search, agent trigger endpoints
- Celery ingestion pipeline with pgvector indexing and S3 document storage
- Next.js TypeScript frontend — chat, document library, workspace settings (Tailwind)
- LangGraph agent templates — classify, summarize, route, notify workflow
- LiteLLM multi-provider router with OpenAI, Claude, and Gemini fallback chains
- Langfuse project — traces, eval datasets, cost dashboards
- Docker Compose for local dev; production Terraform for ECS or Cloud Run
- GitHub Actions CI/CD — lint, test, eval gate, deploy staging/prod
- OpenAPI specs + generated TypeScript client; operator and security runbooks
Effort estimate
Indicative effort for MVP through production hardening (assumes single senior full stack engineer, designer assets available, no custom mobile app):
| Scope | Hours (range) |
|---|---|
| Phases 1–6 (SaaS core + RAG + agents + deploy + hardening) | 280–420 hrs |
| GraphQL API layer (nice-to-have) | +40–60 hrs |
| Pinecone migration + dual-write period | +30–50 hrs |
| Kubernetes migration (from ECS/Cloud Run) | +60–100 hrs |
| Ongoing feature sprints (post-MVP) | 20–40 hrs/week retainer |
| Platform costs (indicative monthly at early SaaS scale) | LLM tokens, ECS/Cloud Run, Postgres, S3 — typically USD 800–4,000 |
The hour range reflects design system maturity, number of document types in ingest, and agent workflow complexity. A $100 fixed-price posting would scope a discovery milestone or technical audit only — a production MVP typically aligns with Phase 1–3 (roughly 120–180 hrs) as a first engagement, with Phases 4–6 on retainer or contract-to-hire.
Glossary
| Term | Meaning |
|---|---|
| DRF | Django REST Framework — serializers, viewsets, and permissions for Django APIs |
| RAG | Retrieval-augmented generation — LLM answers grounded in retrieved document chunks |
| LangGraph | Library for building stateful agent workflows as directed graphs with checkpoints |
| pgvector | PostgreSQL extension for storing and querying embedding vectors |
| LiteLLM | Unified proxy/router for multiple LLM provider APIs with fallback support |
| SSE | Server-Sent Events — HTTP streaming protocol used for chat token delivery |
| Tenant isolation | Architectural guarantee that one organization's data cannot appear in another's retrieval results |
| Celery | Distributed task queue for running async Python jobs outside web request cycles |
| Langfuse | Observability platform for LLM application traces, evaluations, and prompt management |
| BFF | Backend-for-frontend — optional Next.js API routes aggregating Django and FastAPI calls |