RAG Pipeline: Complete Node.js Implementation Guide A developer published a guide to building production RAG systems in Node.js, covering setup, database schema with pgvector, and multi-tenant architecture. The tutorial includes code examples for PostgreSQL, Claude embeddings, and vector search, emphasizing tenant isolation and performance optimization. Build production RAG systems in Node.js - Know where it breaks, why it works, and when to use it 👦 Nephew: Uncle, why would I build RAG in Node.js? I thought this was AI stuff? 👨🦳 Uncle: Good question. Node.js is perfect for RAG because: Plus, you probably already have Node.js running your backend. Why add Python? 👦 Nephew: So I can build the whole thing in JavaScript? 👨🦳 Uncle: Yes. Frontend, backend, RAG - all JavaScript. That's the beauty. But we need to be honest about limitations. Let's talk about that too. Create project mkdir rag-system cd rag-system Initialize Node.js npm init -y Install dependencies npm install express dotenv @anthropic-ai/sdk pg pg-promise cors body-parser npm install --save-dev nodemon typescript @types/node Optional but recommended for production npm install winston helmet compression rag-system/ ├── src/ │ ├── config/ │ │ ├── database.ts PostgreSQL + pgvector setup │ │ └── embedding.ts Claude embeddings │ ├── services/ │ │ ├── retrieval.ts Vector search logic │ │ ├── reranking.ts Two-stage ranking │ │ ├── queryProcessing.ts Query expansion │ │ └── safety.ts Hallucination prevention │ ├── routes/ │ │ └── rag.ts API endpoints │ ├── utils/ │ │ ├── logger.ts Logging critical for debugging │ │ └── metrics.ts Track recall, precision │ └── index.ts Main server ├── .env Secrets ├── package.json └── tsconfig.json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": "ES2020" , "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } } 👨🦳 Uncle: This is your foundation. Get it wrong, everything breaks. -- Connect to PostgreSQL psql -U postgres -- Create database CREATE DATABASE rag system; -- Connect to the database \c rag system -- Install pgvector extension CREATE EXTENSION IF NOT EXISTS vector; -- Create resumes table CREATE TABLE resumes id UUID PRIMARY KEY DEFAULT gen random uuid , tenant id UUID NOT NULL, candidate name VARCHAR 255 NOT NULL, raw text TEXT NOT NULL, created at TIMESTAMP DEFAULT CURRENT TIMESTAMP, -- CRITICAL: tenant isolation CONSTRAINT tenant isolation UNIQUE tenant id, id ; -- Create chunks table where vectors live CREATE TABLE resume chunks id SERIAL PRIMARY KEY, resume id UUID NOT NULL REFERENCES resumes id ON DELETE CASCADE, tenant id UUID NOT NULL, chunk text TEXT NOT NULL, chunk index INTEGER NOT NULL, -- The vector: 1536 dimensions for Claude embeddings embedding vector 1536 NOT NULL, -- Metadata for debugging created at TIMESTAMP DEFAULT CURRENT TIMESTAMP, updated at TIMESTAMP DEFAULT CURRENT TIMESTAMP, -- CRITICAL: Always check tenant CONSTRAINT tenant isolation chunks FOREIGN KEY tenant id REFERENCES tenants id ; -- Create indexes -- 1. Vector index for fast search MOST IMPORTANT CREATE INDEX idx resume chunks embedding ON resume chunks USING ivfflat embedding vector cosine ops WITH lists = 100 ; -- 2. Tenant index security CREATE INDEX idx resume chunks tenant ON resume chunks tenant id, resume id ; -- 3. Text search index keyword search CREATE INDEX idx resume chunks text ON resume chunks USING GIN to tsvector 'english', chunk text ; -- Create tenants table multi-tenancy CREATE TABLE tenants id UUID PRIMARY KEY DEFAULT gen random uuid , name VARCHAR 255 NOT NULL, api key VARCHAR 255 UNIQUE NOT NULL, created at TIMESTAMP DEFAULT CURRENT TIMESTAMP ; -- Create query logs for metrics CREATE TABLE query logs id SERIAL PRIMARY KEY, tenant id UUID NOT NULL REFERENCES tenants id , query TEXT NOT NULL, latency ms INTEGER NOT NULL, recall DECIMAL 3,2 , precision DECIMAL 3,2 , cost cents INTEGER, created at TIMESTAMP DEFAULT CURRENT TIMESTAMP ; -- Create index on query logs for analytics CREATE INDEX idx query logs tenant ON query logs tenant id, created at DESC ; 👨🦳 Uncle: This is where your first failure point lives. python // src/config/database.ts import pgPromise from 'pg-promise'; import dotenv from 'dotenv'; import logger from '../utils/logger'; dotenv.config ; const initOptions = { // Detailed error info critical for debugging error error: any, context: any { logger.error 'Database Error', { error: error.message, query: context.query, params: context.params } ; }, // Connection events connect client: any { logger.info 'Database connected' ; }, disconnect client: any { logger.info 'Database disconnected' ; } }; const pgp = pgPromise initOptions ; const db = pgp { host: process.env.DB HOST || 'localhost', port: parseInt process.env.DB PORT || '5432' , database: process.env.DB NAME || 'rag system', user: process.env.DB USER || 'postgres', password: process.env.DB PASSWORD, // Connection pooling max: 20, // Timeout after 5 seconds connectionTimeoutMillis: 5000, // Idle timeout idleTimeoutMillis: 30000, } ; // Test connection on startup export async function initializeDatabase { try { await db.one 'SELECT 1' ; logger.info '✓ Database connection verified' ; } catch error { logger.error '✗ Database connection failed', { error } ; process.exit 1 ; } } export default db; .env DB HOST=localhost DB PORT=5432 DB NAME=rag system DB USER=postgres DB PASSWORD=your secure password ANTHROPIC API KEY=sk-ant-... ANTHROPIC MODEL=claude-3-5-sonnet-20241022 NODE ENV=production PORT=3000 Security ADMIN API KEY=super-secret-key-change-this 👨🦳 Uncle: This is where the first real cost happens. Know what can fail here. python // src/config/embedding.ts import Anthropic from '@anthropic-ai/sdk'; import logger from '../utils/logger'; const client = new Anthropic { apiKey: process.env.ANTHROPIC API KEY } ; interface EmbeddingResult { text: string; embedding: number ; } / Get embeddings for text chunks. ⚠️ FAILURE POINTS: 1. API rate limit 429 - implements exponential backoff 2. Token too long 4096 tokens max - chunks pre-validated 3. Network timeout - retry logic built in 4. Cost tracking - logs cost per embedding / export async function getEmbeddings texts: string : Promise