FlowKit

Building a RAG pipeline with n8n and Supabase pgvector, step by step

Published 14 April 2026 · 3 min read

RAG — Retrieval-Augmented Generation — is how you get an LLM to answer from your documents instead of its training data. n8n's LangChain nodes plus Supabase's pgvector extension are the leanest production-grade stack we know for it: no dedicated vector database, no framework code, one free Postgres. Here's the complete build.

The architecture in one paragraph

Documents go through an ingestion pipeline: text extraction, splitting into ~1,000-character chunks, embedding each chunk into a 1,536-dimension vector (OpenAI text-embedding-3-small), and inserting chunk + metadata + vector into a Postgres table. At question time, the retrieval pipeline embeds the question in the same vector space, fetches the closest chunks via similarity search, injects them into the prompt, and the model answers from that context only, citing sources.

Step 1: prepare Supabase

In the Supabase SQL editor:

create extension if not exists vector;

create table if not exists documents (
  id bigserial primary key,
  content text,
  metadata jsonb,
  embedding vector(1536)
);

create function match_documents (
  query_embedding vector(1536),
  match_count int default null,
  filter jsonb default '{}'
) returns table (id bigint, content text, metadata jsonb, similarity float)
language plpgsql as $$
begin
  return query
  select documents.id, documents.content, documents.metadata,
         1 - (documents.embedding <=> query_embedding) as similarity
  from documents
  where documents.metadata @> filter
  order by documents.embedding <=> query_embedding
  limit match_count;
end;
$$;

Two things to never get wrong: the vector dimension (1536 here) must match your embedding model, and the function must be named match_documents — it's the convention n8n's Supabase vector store node calls.

Step 2: the ingestion workflow

In n8n, the insert side is one root node with three sub-nodes:

  • Supabase Vector Store (mode insert, table documents) — the root.
  • Default Data Loader (ai_document) — extracts text; PDF loading is built in.
  • Recursive Character Text Splitter (ai_textSplitter) — 1,000 characters, 150 overlap is a solid default for business documents.
  • OpenAI Embeddings (ai_embedding) — text-embedding-3-small.

Front it with a webhook accepting file uploads and you can index any PDF with curl -F 'file=@doc.pdf'. Attach a source metadata field at load time: it's what your chatbot will cite later, and what you'll filter on when you need to re-index a single document (delete from documents where metadata->>'source' = '…').

Step 3: the chat with citations

The retrieval side mirrors it: a Chat Trigger (n8n hosts the chat UI at a public URL), a Retrieval Q&A Chain as root, and underneath: the chat model, a Vector Store Retriever (topK 4), the same Supabase vector store in retrieve mode, and the same embeddings node. Six nodes total.

The prompt does the heavy lifting. Three constraints turn a generic bot into a trustworthy one:

  1. Answer only from the provided context ({context} placeholder).
  2. Cite the source of every claim, [source], using the chunk metadata.
  3. If the context doesn't contain the answer, say so — never improvise.

Tuning that actually matters

  • Chunk size: shorter (500–700) for FAQ-style content, longer (1,200–1,500) for contracts where clauses need their surroundings. Re-index after changing it.
  • topK: 4 is right for focused questions; 6–8 helps cross-document questions at the cost of noise and tokens.
  • Freshness: schedule re-indexing (nightly Notion sync, Drive triggers). A RAG that answers correctly from last quarter's policy is worse than no RAG.
  • Model: gpt-4o-mini handles most corpora; upgrade only if answers miss nuance that's demonstrably in the retrieved chunks.

Common failure modes

Empty answers usually mean the match_documents function is missing or the table is empty; dimension-mismatch errors mean the embedding model and column disagree; wrong-language answers mean your prompt doesn't pin the reply language. All three take minutes to fix once identified — and they're the exact troubleshooting section of the RAG Assistant Pack, which ships this entire architecture as four importable workflows: PDF ingestion, Notion sync, the citation chatbot, and a REST API on top of the same index.