You can stand up a genuinely useful retrieval-augmented chatbot in a weekend with three moving parts: Postgres (plus the pgvector extension) as your vector store, a FastAPI service as the glue, and Claude for the generation step. The one thing that trips people up on day one is that Claude has no embeddings endpoint — you bring your own embedding model, and everything else is standard web plumbing. What follows is the shape of that build, the code that matters, and the honest limits of doing it this cheaply.

What is each piece actually doing?

RAG is less mysterious than the acronym suggests. At query time you embed the user's question into a vector, find the most similar chunks of your own documents, paste those chunks into a prompt, and ask Claude to answer using only that context. Three responsibilities map cleanly onto three tools:

pgvector stores chunk embeddings and answers "which chunks are closest to this question?" with a single SQL ORDER BY. If you already run Postgres, you don't need a separate vector database to start.

FastAPI exposes an HTTP endpoint, validates input with Pydantic, and orchestrates the retrieve-then-generate flow.