Web ApplicationAI/LLMInfrastructure
LiveJan 2026 – Present

Document Q&A SaaS

Multi-tenant RAG-powered document intelligence, self-hosted at $0/month.

SupabasePostgreSQLpgvectorDeno Edge FunctionsReactTypeScriptDocker

The Problem

Teams drown in documents. They need to ask natural-language questions across their files and get accurate, sourced answers — not hallucinations. Existing solutions are expensive (per-seat SaaS pricing) or don't provide tenant isolation for multi-org deployments.

The Approach

I built a full multi-tenant SaaS from scratch — not on someone else's platform, but on my own self-hosted Supabase instance running 13 Docker containers on a dedicated Ubuntu server.

Key architectural decisions

Per-tenant PostgreSQL schema isolation instead of row-level security — each tenant gets a dedicated schema with its own database role. Stronger isolation, no cross-tenant data leakage risk, and clean tenant provisioning/teardown.

Serverless TypeScript edge functions instead of a monolithic backend — each function is independently deployable, handling a single domain (auth, ingestion, search, chat, etc.).

Vector search in the primary database instead of a dedicated vector DB — one database, one backup strategy, one operational surface. Handles both keyword and semantic search.

Self-hosted Supabase instead of managed cloud — full control over infrastructure, zero cloud bills, and the ability to customize the stack for the specific use case.

Technical Deep-Dive

RAG Pipeline (the core AI system)

  1. 1.Document ingestion: User uploads documents → stored in object storage with tenant-scoped paths
  2. 2.Chunking: Documents split into optimized chunks for retrieval quality
  3. 3.Embedding: Chunks embedded via embedding API → stored in tenant's vector table
  4. 4.Retrieval: User query → vector + keyword hybrid search → top-k relevant chunks retrieved
  5. 5.Generation: Retrieved chunks + conversation history (sliding window) → LLM streaming response with source citations

Multi-tenant architecture

  1. Automated tenant provisioning: new tenant → isolated schema → dedicated role → tables + permissions. Zero-touch onboarding.
  2. Each tenant's data (documents, embeddings, chat history) is fully isolated. A compromised tenant role cannot access another tenant's data.

Third-party integration

  1. OAuth2 flow with selective folder sync — users choose which folders to import
  2. Real-time sync status dashboard showing per-folder import progress
  3. Background sync with retry logic for API failures

Key Metrics

13
Docker containers running the full Supabase stack
$0/month
infrastructure cost (self-hosted on UN1290)
Per-tenant
schema isolation with dedicated database roles
Sliding-window
conversation history with streaming chat

Challenges & Solutions

Challenge 1:Chunking strategy

Initial naive chunking produced poor retrieval quality. Chunks would split mid-sentence, losing context. Fix: Switched to optimized chunking with overlap, ensuring each chunk is semantically coherent.

Challenge 2:Multi-tenant provisioning

Creating schemas, roles, and tables manually for each tenant doesn't scale. Fix: Built an automated provisioning engine that handles the entire tenant onboarding flow in a single function call.

Challenge 3:Self-hosted Supabase complexity

13 containers means 13 things that can break. Docker networking, volume persistence, and container orchestration all required careful configuration. Fix: Documented every container's purpose and dependency, set up proper Docker Compose health checks, and automated PostgreSQL backups with 7-day retention.

Lessons Learned

01

Keeping vectors in the primary database simplifies operations. One database to back up, one connection string to manage. Dedicated vector DBs add operational overhead that isn't justified at this scale.

02

Schema isolation > row-level security for multi-tenant SaaS. RLS is simpler to set up but harder to audit and debug. Schema isolation is more work upfront but gives you clean boundaries and zero cross-tenant risk.

03

Self-hosting forces you to understand infrastructure. When a managed service handles your storage, you don't think about volume mounts. When you self-host, you learn Docker volumes, backup strategies, and what happens when a container crashes at 3 AM.

Ask me anything