Building a Centralized Vector Database Pipeline for Multi-Project RAG

How I built a single, admin-controlled service that lets every project in my organization embed and retrieve data from its own isolated vector store

If you’ve worked on more than one Retrieval-Augmented Generation (RAG) project, you’ve probably run into the same annoying pattern: every project ends up with its own little vector store, its own embedding logic, its own duplicate code for chunking files, and its own inconsistent way of tracking what’s actually been indexed.

I got tired of that, so I built a centralized vector database service that every project in my organization can plug into. One backend, one embedding model, one clean set of endpoints — and every project gets its own isolated, admin-controlled storage space.

Here’s how it works.

The Problem

When you’re running multiple RAG-powered projects at once, a few pain points show up fast:

  • Every team reinvents chunking and embedding logic
  • There’s no single place to see what data lives where
  • Deleting or updating stored documents becomes a manual, error-prone process
  • Nobody has a clear picture of which files are indexed in which project

I wanted one system that solves this once, for everyone.

The Idea: One Service, Many Isolated Databases

Instead of giving each project its own standalone vector database, I built a shared service where:

  • Each project gets its own named storage directory
  • All directories live under one base storage path
  • An admin layer controls the full lifecycle — create, insert, update, delete, list — across every project’s storage
  • Every project only ever talks to a small set of simple endpoints to embed and retrieve its own data

This means projects don’t need to know anything about vector databases, embedding models, or similarity search internals. They just send text in and get relevant results back.

Architecture Overview

Here’s the high-level flow:

Press enter or click to view image in full size

In plain terms:

  1. A project sends a file or text to the service
  2. The service breaks it into clean text chunks
  3. Those chunks get embedded and stored (upserted) into that project’s own FAISS index
  4. Later, the project sends a query, and the service returns the most similar stored chunks
  5. An admin layer sits on top of all of this, with full control to create, update, or delete data across any project’s storage

What’s Under the Hood

  • Embedding model: a lightweight sentence-transformer model, chosen for speed and low resource usage
  • Vector engine: FAISS, for fast similarity search at scale
  • Backend framework: a modern Python web framework built for speed and simplicity
  • Storage layout: every project’s database lives in its own folder, containing:
  • the FAISS index itself
  • a metadata/pickle file for the index
  • a tracked-files registry (so you always know what’s indexed)
  • a source map (so you always know how many chunks came from each file)

Each project is fully sandboxed. Nothing bleeds across storage directories.

The Core Workflow

Every project follows the same simple lifecycle:

1. Create a storage directory

A new, isolated space is created for the project. Invalid or unsafe directory names are automatically rejected.

2. Process a file into chunks

Upload a document (PDF, TXT, DOCX, or Markdown) and it comes back as clean, ready-to-embed text chunks. This step doesn’t store anything yet — it just prepares the data.

3. Upsert the chunks

The chunks get embedded and stored. If the project’s index doesn’t exist yet, it’s created automatically. If it does exist, new vectors are simply appended. Duplicate sources are automatically prevented.

4. Search

A query comes in, gets embedded the same way, and the service returns the top-k most similar chunks — along with which source file they came from. A similarity score threshold filters out weak matches.

5. Manage the data

At any point, an admin can:

  • List every database in the system, with file counts and tracked sources
  • Delete a specific file’s vectors from a project’s index
  • Have all of this triggered externally through a single webhook event, so other systems can kick off any step of this pipeline programmatically

Why This Matters

The real win here isn’t the vector search itself — FAISS and sentence-transformers are well-understood tools. The win is centralization with isolation:

  • One codebase to maintain instead of N duplicated ones
  • One admin view into every project’s stored data
  • Every project gets embedding and retrieval “for free,” without owning any of the infrastructure
  • Adding a brand-new project to RAG-powered search takes minutes: create a directory, start upserting

It turns “set up a vector database” from an infrastructure task into a two-endpoint integration for whoever’s building the next project.

What’s Next

A few directions I’m considering for this pipeline:

  • Authentication and per-project access scoping
  • Async batch processing for very large files
  • Pluggable embedding models per project (not just one global model)
  • A lightweight admin dashboard on top of the existing list/delete endpoints

If you’re building multiple RAG projects and keep rebuilding the same vector storage logic every time, this pattern — one shared service, isolated storage per project, centralized admin control — is worth stealing.

Have you built something similar, or run into different tradeoffs with multi-project RAG infrastructure? I’d love to hear how you approached it.

1 Like