Building B2B AI Agents on Supabase and PostgreSQL: A Secure Architecture Guide
How to architect production-grade B2B AI agents using Supabase for tenant isolation, pgvector for semantic search, and pg_boss for durable multi-step workflows.
Key Takeaways
- Multi-tenant B2B AI agents require database-level tenant isolation. Row-Level Security (RLS) in PostgreSQL is the most robust way to prevent cross-tenant prompt leaks.
- A unified database (Postgres) is superior to split-database setups (a relational DB + a standalone vector DB) for B2B applications because it maintains transactional integrity and simplifies metadata filtering.
- pgvector enables fast semantic search directly inside Postgres, allowing developers to run hybrid searches (vector similarity + pg_trgm text matching) in a single query.
- Multi-step agent tasks must be durable. pg_boss provides reliable, Postgres-backed queues to handle job retries, priority levels, and human-in-the-loop approvals.
- Large raw files (captures, media, PDFs) should reside in cheap object storage (Cloudflare R2), while Supabase stores structured metadata and vector embeddings.
Building a personal AI assistant or a toy chatbot is easy. Building a production-grade B2B AI agent that enterprise clients can trust with their actual data is a completely different engineering challenge. Enterprise B2B agents demand absolute tenant isolation, auditability, strict data governance, and resilience against transient network faults.
For years, the standard AI builder advice was to spin up a relational database for user data, a specialized vector database for semantic search, and an external microservice queue for background workers. This split-state architecture is a breeding ground for synchronization bugs, data leakage, and high infrastructure bills.
At Game Changer Labs, we reject this complexity. The modern standard for secure, resilient B2B agents is a unified architecture built around Supabase (PostgreSQL), pgvector for semantic search, and pg_boss for durable job queues, backed by Cloudflare R2 for raw file storage. Here is the complete guide to implementing this architecture in production.
The B2B Stack Architecture
A secure B2B agent needs a database that handles relationships, vector calculations, and task status in one transactional boundary. The table below compares this unified Postgres-first stack against the legacy split-service stack:
| Architecture Layer | Legacy Split Stack | Unified Postgres-First Stack | Primary Benefit |
|---|---|---|---|
| Relational State | PostgreSQL / MySQL | Supabase (PostgreSQL) | Single source of truth for all metadata |
| Vector Storage | Pinecone / Milvus / Chroma | PostgreSQL + pgvector | No sync lag; metadata filtering uses standard SQL |
| Durable Jobs | Temporal / BullMQ + Redis | PostgreSQL + pg_boss | No separate cluster; transactional job creation |
| Blob Storage | AWS S3 | Cloudflare R2 | Zero egress fees for raw documents and captures |
| Tenant Security | Application-level checks | Row-Level Security (RLS) | Database-enforced tenant boundaries |
1. Tenant Security: Enforcing Boundaries via RLS
In B2B SaaS, the absolute worst-case failure mode is a data leak between tenants. If an AI agent fetches document chunks from Tenant A to answer a question for a user in Tenant B, your product is dead.
Relying on application-level filters (e.g., where tenant_id = x in every query) is a risk. One missed clause in a complex retrieval query is all it takes to leak data. The solution is PostgreSQL Row-Level Security (RLS).
By enabling RLS in Supabase, the database itself filters rows before returning them to your application. Even if your agentic prompt is compromised and attempts to scan all documents, PostgreSQL prevents it from seeing other tenants' data:
-- Enable Row-Level Security on our memory table
ALTER TABLE memories ENABLE ROW LEVEL SECURITY;
-- Create a policy ensuring users can only read memories belonging to their tenant
CREATE POLICY tenant_isolation_policy ON memories
FOR ALL
USING (tenant_id = auth.jwt() ->> 'tenant_id');Because Supabase JWTs encode the user's tenant metadata, the database automatically filters out unauthorized rows at the query boundary, providing a mathematical guarantee of tenant isolation.
2. Semantic Retrieval: Hybrid Search via pgvector
AI agents rely on semantic search to pull context from a knowledge base (Retrieval-Augmented Generation, or RAG). While vector search is powerful, it is rarely sufficient on its own. B2B users expect exact keyword matching to work alongside semantic queries.
By using pgvector, we can run a hybrid search—combining vector similarity with PostgreSQL full-text trigram matching—in a single, unified SQL statement:
-- Perform a hybrid search combining cosine similarity and text similarity
SELECT id, body,
(1 - (embedding <=> :query_embedding)) * 0.7 +
similarity(body, :query_text) * 0.3 AS score
FROM memories
WHERE tenant_id = :tenant_id
ORDER BY score DESC
LIMIT 5;This hybrid query scores and ranks results in a single step, ensuring that exact keywords (like product names or IDs) and semantic concepts are matched, while RLS guarantees the search never crosses tenant boundaries.
3. Task Durability: Orchestrating Loops with pg_boss
Unlike chatbots, which return an answer instantly, agents run in loops. They scrape URLs, evaluate outcomes, call APIs, and wait for approvals. These operations are slow and prone to timeouts or network drops.
If a server restarts while an agent is executing a multi-step task, a standard memory queue (like a Node event loop) will lose that job. We need durable persistence.
pg_boss is a queueing system that uses PostgreSQL as its job store. It runs on your existing Supabase database without requiring a separate Redis cluster. Because the jobs are stored in database rows, creating a job and updating app state can happen inside the same database transaction:
import PgBoss from 'pg-boss';
const boss = new PgBoss(process.env.DATABASE_URL);
await boss.start();
// Publish a background agent run job
const jobId = await boss.send('agent_run', {
agentId: 'agent_981',
task: 'Audit Q3 invoices for compliance',
tenantId: 'tenant_abc'
});If your server crashes, the pg_boss worker picks up the job exactly where it left off, preventing failed agent runs. Furthermore, pg_boss supports human-in-the-loop approvals by letting you pause a job and resume it when the tenant approves the action via the UI.
4. Storage Architecture: The Raw-vs-Metadata Split
AI agents process a massive volume of unstructured data—PDF uploads, web captures, transcripts, and preview assets. Storing these directly in your database is highly inefficient and drives up database hosting costs.
The standard pattern is the raw-vs-metadata split:
- Cloudflare R2 stores the raw, binary assets (PDFs, media, large HTML strings). Egress is free, making it ideal for agents that frequently fetch and scrape documents.
- Supabase (PostgreSQL) stores the structured metadata (file paths, creation dates, ownership) and the vector embeddings generated from text chunks.
When the agent needs to retrieve information, it queries Supabase for the relevant text embeddings. It only accesses R2 when it needs to read the original raw file.
Building for the Future
By consolidating your database, vector storage, and job queue into a single Supabase/Postgres instance, you eliminate sync lag, guarantee tenant isolation via RLS, and secure your workflows with pg_boss. This is the stack that Game Changer Labs uses to build secure enterprise AI systems.
If you are looking to design and build a secure, multi-tenant AI agent or MVP, check out our AI Cost Estimator to get a scoping budget, or contact our team to discuss your architecture.
Frequently Asked Questions
Why use Supabase/PostgreSQL instead of a specialized vector database?
Specialized vector databases excel at raw vector similarity at massive scales, but B2B AI applications rarely need billions of vectors. B2B agents rely heavily on rich relational metadata (user accounts, tenant rules, permissions). By using PostgreSQL with the pgvector extension, you can query vectors and filter metadata in a single transactional query, eliminating data sync bugs and maintaining strict Row-Level Security.
How does Row-Level Security (RLS) protect B2B AI agents?
In a multi-tenant B2B application, a single leak of another customer's data is catastrophic. RLS policies apply rules directly to table rows based on the authenticated user's ID or tenant ID. Even if your agent's LLM prompt is manipulated or compromised, PostgreSQL guarantees that the database will only return data belonging to that specific tenant, creating a hard mathematical boundary around sensitive client data.
What is pg_boss and why is it needed for agents?
pg_boss is a job queue for Node.js that runs on top of PostgreSQL. AI agents frequently execute long-running, multi-step workflows (like scraping a page, generating a summary, sending a draft). If a server crashes mid-task, a plain memory queue will lose the task. pg_boss guarantees durability, handles retries, schedules cron tasks, and allows pausing jobs for human approval.
How should files and metadata be split in an agent stack?
Adopt the raw-vs-metadata split: store large raw documents, screenshots, and media in Cloudflare R2 (or AWS S3) for low-cost storage and free egress. Store the extracted text, chunk metadata, and vector embeddings in Supabase/PostgreSQL. Your application code and vector retrieval query Supabase, never R2 directly.
Free Tools
Have a project that needs to ship?
Game Changer Labs designs and builds production systems across AI, neurotech, civic, and spatial computing. Tell us what you are building and we will scope it.
Keep Reading
Get new playbooks by email
Occasional, no-fluff field notes on building production AI — new guides and tools, straight to your inbox. Unsubscribe anytime.