AI · Data · Security · 2026
Permission-aware AI search across many companies' data
A multi-tenant AI search assistant (RAG) on PostgreSQL and pgvector for a SaaS product: staff get answers only from records they may see.
- 01QuestionAsked in the staff member's own words.
- 02PlanThe model picks search, SQL or both, guided by business terms.
- 03Permission filterGateCompany schema, groups and shared people decide what can be read.
- 04RerankHybrid search, then in-process reranking puts the best record first.
- 05AnswerCited sources, with Right/Wrong marks for reviewing misses.
- questions with the right record first after reranking, up from 28
- 34/40
- question types answered with SQL planning, up from 5
- 12/13
- per question with a term picker, down from about 38 s
- ~12 s
Context
Data must not cross between client companies, and an HR record must not reach a sales employee. Self-serve ruled out asking clients to restructure data.
My role
Solo: architecture, code, evaluation and the Docker Compose setup.
What I built
- Architecture: pgvector as main store and Pinecone behind one interface, so features need no store branches.
- Frontend: Chat screen with cited sources and Right/Wrong marks plus comments for reviewing misses.
- Backend: FastAPI service; PostgreSQL and Dropbox connectors tag chunks with company, groups and shared people.
- Data & AI: Hybrid search, in-process reranking, and model-planned search, SQL or both, guided by business terms.
- Security: Model-written SQL runs read-only behind row-level security and a parser check; uploads parse in time-limited child processes.
- Infrastructure & DevOps: Docker Compose; one command builds each company's schema, indexes and logins from config.
- Testing: 486 automated tests, including isolation on both stores; five before/after evaluations decided what stayed.
Hard problems and decisions
- Shared index or schema per company. I chose schemas, so the database, not application code, blocks cross-company reads. Cost: more objects.
- Model-written SQL. I chose a synced copy over live client databases: no load on clients, but data only as fresh as the last sync.
- Too many business terms. 300 terms cost about 38 s per question; a picker cut it to about 12 s, with the right terms for 41 of 41 test questions.
Outcome
On a synthetic evaluation set: reranking put the right record first for 34 of 40 questions (from 28); SQL planning answered 12 of 13 question types (from 5); terms lifted a wording test from 44 to 51 of 53.
Stack
Python, FastAPI, PostgreSQL, pgvector, Pinecone, Ollama, Dropbox API
Areas
Architecture, Frontend, Backend, Data, AI, Security, Infrastructure & DevOps, Testing
Period
Oct 2026 – present