FlowKit

Connecting n8n to Supabase: the complete guide (auth, queries, vectors)

Published 18 July 2026 · 4 min read

Close-up of a dark blue printed circuit board with gold traces
fig. 01four doors into Supabase from n8n

Supabase is the most profitable backend to know when you automate with n8n: managed Postgres, an auto-generated REST API, built-in authentication and pgvector for AI — all with a generous free tier. This guide covers the four ways to wire it to n8n: the Supabase node for CRUD, the auth API for managing users, RPC for Postgres functions, and vectors for RAG.

1. The credential: service_role, and why

In n8n: Credentials → New → Supabase API. Two fields:

  • Host: the project URL, https://your-project.supabase.co (under Project Settings → API);
  • Service Role Secret: the service_role key — not the anon key.

Why service_role? Because n8n is a trusted backend: your workflows need to read and write without being blocked by Row Level Security. Immediate corollary: this key bypasses all your RLS policies. It must never appear client-side, nor in a webhook response sent back to a browser. When a workflow must act on behalf of a specific user, skip the Supabase node and call the REST API with the user's JWT (section 3).

2. CRUD: the Supabase node day to day

Example table — incoming leads to enrich:

create table leads (
  id uuid primary key default gen_random_uuid(),
  email text not null unique,
  source text,
  score int,
  processed boolean default false,
  created_at timestamptz default now()
);

The four operations of the Supabase node (resource Row):

  • Create: map the columns (email, source) from the previous node's data. Trap: a uniqueness violation (duplicate email) fails the item — enable Settings → On Error → Continue if duplicates are a normal case.
  • Get Many: tick Use Custom Filters for PostgREST syntax. Real example — unprocessed leads with a score of at least 60: processed=eq.false&score=gte.60&order=created_at.desc&limit=20.
  • Update: filter id=eq.{{ $json.id }}, then the columns to change (processedtrue). Without a filter, PostgREST refuses — that is your safety net against an accidental global update.
  • Delete: same filter logic. Often prefer an archived=true update: a workflow mass-deleting on a badly written filter is unforgiving.

The PostgREST operators worth knowing: eq, neq, gt/gte, lt/lte, like.*pattern*, ilike (case-insensitive), in.(a,b,c), is.null.

3. Auth: creating and signing in users from n8n

The Supabase node does not handle authentication — that is the GoTrue API's job, called with an HTTP Request node. Three calls cover the essentials.

Create a user (as admin, with the service_role key):

POST https://your-project.supabase.co/auth/v1/admin/users
Headers:
  apikey: <service_role>
  Authorization: Bearer <service_role>
Body (JSON):
  { "email": "client@example.com", "password": "a-strong-password",
    "email_confirm": true }

Sign a user in (get their JWT):

POST https://your-project.supabase.co/auth/v1/token?grant_type=password
Headers:
  apikey: <anon>
  Content-Type: application/json
Body (JSON):
  { "email": "client@example.com", "password": "a-strong-password" }

The response contains access_token: the user's JWT, valid for one hour.

Query as the user — this is where RLS kicks back in. Call the REST API with the JWT instead of the service_role key:

GET https://your-project.supabase.co/rest/v1/leads?select=*
Headers:
  apikey: <anon>
  Authorization: Bearer {{ $json.access_token }}

With an RLS policy like this one, each user only sees their own rows — even through n8n:

alter table leads enable row level security;

create policy "users see their own leads"
  on leads for select
  using (auth.uid() = owner_id);

4. RPC: calling your Postgres functions

Every Postgres function is exposed at /rest/v1/rpc/<name>. It is the bridge between n8n and your SQL logic — including match_documents, the vector similarity function used by RAG:

POST https://your-project.supabase.co/rest/v1/rpc/match_documents
Headers:
  apikey: <service_role>
  Authorization: Bearer <service_role>
  Content-Type: application/json
Body (JSON):
  { "query_embedding": [0.0123, -0.0456, ...],
    "match_count": 4,
    "filter": { "source": "product-faq" } }

Useful when you want vector search without the LangChain nodes — for instance to return raw passages from an API.

5. Vectors: pgvector and the Supabase Vector Store node

For RAG, n8n ships a dedicated node, Supabase Vector Store, which reuses the same credential and expects the documents table + the match_documents function (the full SQL script is in our step-by-step pgvector guide). Three modes to remember:

  • Insert Documents: ingestion (chunks + embeddings);
  • Retrieve Documents (As Vector Store): retrieval inside a chain;
  • Retrieve Documents (As Tool for AI Agent): the vector store becomes a tool the AI Agent decides to query — the mode our chatbot uses, including on WhatsApp.

Golden rule: the same embedding model at ingestion and retrieval time, and a consistent column dimension (vector(1536) for text-embedding-3-small).

6. When the API is not enough: the Postgres node

Complex joins, aggregations, insert ... on conflict, migrations: switch to the Postgres node with a direct connection. Under Project Settings → Database, take the transaction-mode pooler connection string (port 6543) — n8n workflows open and close connections in bursts, and the pooler is built for that. Keep port 5432 (session mode) for operations that require it (listen/notify, prepared statements).

Going further

You now have the four doors into Supabase from n8n. The logical next step: the complete pgvector guide to build the vector side end to end, then the RAG Assistant Pack (€119) — PDF ingestion, citations chatbot, Notion sync and the /ask API, four n8n workflows on Supabase, tested, documented, ready to import.

FAQ

Frequently asked questions

Which Supabase key should I use in n8n: anon or service_role?

The Supabase node credential expects the service_role key: n8n is a trusted backend and usually needs to write everywhere. Careful, this key bypasses Row Level Security — never expose it client-side, and if a workflow must act on behalf of a user, call the REST API with that user's JWT via an HTTP Request node instead.

Supabase node or Postgres node: which one should I pick?

The Supabase node goes through the REST API (PostgREST): perfect for simple CRUD, filters included, with no connection pool to manage. The Postgres node connects directly to the database (via the pooler, port 6543 in transaction mode): essential for raw SQL, complex joins, aggregations and migrations.

How do I call a Postgres function (RPC) from n8n?

The Supabase node does not cover RPC: use an HTTP Request node with a POST to https://your-project.supabase.co/rest/v1/rpc/function_name, with the apikey and Authorization: Bearer headers and the function arguments in the JSON body. That is how you call match_documents outside the vector nodes.

Is Supabase's free tier enough for n8n in production?

For reasonable internal use, yes: 500 MB database, pgvector included, REST API with generous limits. Its real constraints: the database pauses after 7 days of inactivity (a scheduled n8n workflow that pings it daily avoids this) and there are no automatic backups — move to the Pro plan as soon as the data matters.

RAG Assistant Pack

€119