TL;DR: „Frag nicht 'BigQuery oder Supabase?' – frag 'Wo leben meine operativen AI-Daten?'. In den meisten Fällen ist das Supabase, nicht das DWH."
— Till FreitagDas Paradigma hat sich verschoben
Klassische DWH-Logik (ETL → Staging → Marts → Reports) war auf Menschen als Konsumenten ausgelegt. In der AI-First Welt ist der primäre Konsument oft ein Agent oder ein LLM – das ändert die Anforderungen fundamental.
Ein Dashboard verzeiht 30 Sekunden Query-Zeit. Ein Agent, der mitten in einem Tool-Call wartet, nicht. Ein BI-Analyst weiß, dass rev_net_eur_q der Quartalsumsatz ist. Ein LLM rät – und liegt manchmal daneben.
Was ein AI-First Stack braucht
| Anforderung | Warum |
|---|---|
| Semantic Layer | Agenten brauchen Bedeutung, nicht nur Spalten |
| Vector + Relational | Structured queries UND similarity search |
| Low latency reads | Streaming/Realtime für Agents, nicht nur Batch |
| API-first | Direkter Zugriff ohne SQL-Middleware |
| Row-level Security | Agents dürfen nicht alles sehen |
BigQuery vs. Supabase – die ehrliche Antwort
Das sind keine direkten Alternativen, sondern unterschiedliche Schichten:
- BigQuery ist ein analytisches DWH – optimiert für Petabyte-Queries, Batch, BI.
- Supabase ist eine operational database (Postgres) – optimiert für Transaktionen, Realtime, App-Backend.
Wann Supabase zusätzlich sinnvoll ist
- Du brauchst
pgvectorfür Embeddings direkt in der DB - Deine Agenten brauchen Realtime-Subscriptions
- Du willst Row Level Security für Multi-Tenant AI Apps
- Stack ist eher product-nah als analytics-nah
Wann BigQuery bleibt
- Große Datenmengen (>100 GB)
- Komplexe Transformationen mit dbt
- Google Cloud already in use (Vertex AI, Looker)
- BI-heavy Anwendungsfälle
Der pragmatische AI-First Stack 2025/26
Operational Layer: Supabase (Postgres + pgvector + Realtime)
↓
Transformation: dbt Core / dbt Cloud
↓
Analytical Layer: BigQuery (oder DuckDB für kleinere Setups)
↓
Semantic Layer: cube.dev / LookML / MetricFlow
↓
AI Access: LLM + Tool Use → Semantic Layer APIFür kleinere Teams fällt BigQuery oft weg – dann ist DuckDB + Supabase ein extrem schlanker, günstiger Stack.
Konkrete Empfehlung, wenn du heute auf BigQuery sitzt
Wenn du auf BigQuery bist und AI-Features brauchst:
- Supabase parallel für operationale Daten – insbesondere wenn du eigene Produkte baust.
- pgvector in Supabase für Embeddings statt einer separaten Vektordatenbank (Pinecone, Weaviate).
- BigQuery bleibt für Analytics – kein Grund zu migrieren.
- dbt als Bindeglied – Transformationen aus Supabase in BigQuery, sauber dokumentiert.
Die häufigste Falle: Leute ersetzen BigQuery durch Supabase. Das ist die falsche Frage. Die richtige ist: „Wo leben meine operativen AI-Daten?" – und da ist Supabase oft die bessere Antwort als BigQuery.
Falls du klein anfängst und neu aufbaust
DuckDB + Supabase + dbt ist 2026 der leanste Stack mit dem besten AI-Fit – günstig, schnell, local-first möglich, pgvector inklusive. Du kannst lokal entwickeln, prototypisch deployen und erst skalieren, wenn die Datenmengen es wirklich verlangen.
Beispiel-Setup: Supabase + pgvector + dbt + Agent
Damit das nicht abstrakt bleibt – so sieht ein minimales, produktionsnahes Setup aus, das wir in der Praxis genau so bauen.
1. Supabase: Schema mit pgvector
-- Extension einmalig aktivieren
create extension if not exists vector;
-- Operationale Tabelle: Support-Tickets
create table tickets (
id uuid primary key default gen_random_uuid(),
customer_id uuid not null references customers(id),
subject text not null,
body text not null,
status text not null default 'open',
created_at timestamptz default now()
);
-- Embedding-Tabelle (1:1 zu tickets)
create table ticket_embeddings (
ticket_id uuid primary key references tickets(id) on delete cascade,
embedding vector(1536) not null,
updated_at timestamptz default now()
);
-- Vektor-Index für schnelle Similarity Search
create index on ticket_embeddings
using ivfflat (embedding vector_cosine_ops) with (lists = 100);2. Embeddings via Edge Function
Eine Supabase Edge Function hört auf neue Tickets (Webhook oder Trigger) und schreibt das Embedding zurück:
// supabase/functions/embed-ticket/index.ts
const { data: ticket } = await supabase
.from('tickets').select('id, subject, body').eq('id', ticketId).single();
const embedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: `${ticket.subject}\n\n${ticket.body}`,
});
await supabase.from('ticket_embeddings').upsert({
ticket_id: ticket.id,
embedding: embedding.data[0].embedding,
});3. dbt: Semantische Modelle für Analytics
dbt transformiert die operationalen Daten in saubere, dokumentierte Marts – die Doku ist gleichzeitig der Semantic Layer für den Agenten:
# models/marts/fct_tickets.yml
models:
- name: fct_tickets
description: "Ein Ticket pro Zeile, angereichert mit SLA-Status und Kundensegment."
columns:
- name: ticket_id
description: "Primärschlüssel."
- name: time_to_first_response_minutes
description: "Minuten zwischen Ticket-Eingang und erster Mitarbeiter-Antwort."
- name: sla_breached
description: "True, wenn die Erstantwort > 4h gedauert hat."-- models/marts/fct_tickets.sql
select
t.id as ticket_id,
t.customer_id,
c.segment as customer_segment,
extract(epoch from (r.first_response_at - t.created_at))/60
as time_to_first_response_minutes,
case when r.first_response_at > t.created_at + interval '4 hours'
then true else false end as sla_breached
from {{ ref('stg_tickets') }} t
left join {{ ref('stg_customers') }} c on c.id = t.customer_id
left join {{ ref('int_first_response') }} r on r.ticket_id = t.id4. Agent-Zugriff: zwei Tools, klare Trennung
Der Agent bekommt nicht „die Datenbank", sondern zwei eng definierte Tools:
const tools = [
{
name: 'search_similar_tickets',
description: 'Findet semantisch ähnliche, bereits gelöste Tickets.',
parameters: { query: 'string', limit: 'number' },
handler: async ({ query, limit }) => {
const emb = await embed(query);
// RPC mit RLS: gibt nur Tickets zurück, die der User sehen darf
return supabase.rpc('match_tickets', { query_embedding: emb, match_count: limit });
},
},
{
name: 'query_ticket_metrics',
description: 'Fragt aggregierte Kennzahlen aus fct_tickets ab (SLA, Volumen, Segmente).',
parameters: { metric: 'string', dimension: 'string', period: 'string' },
handler: async (args) => semanticLayer.query(args), // cube.dev / MetricFlow
},
];Die zugehörige Postgres-Funktion mit RLS:
create or replace function match_tickets(
query_embedding vector(1536),
match_count int default 5
) returns table (ticket_id uuid, subject text, similarity float)
language sql stable as $$
select t.id, t.subject,
1 - (e.embedding <=> query_embedding) as similarity
from ticket_embeddings e
join tickets t on t.id = e.ticket_id
order by e.embedding <=> query_embedding
limit match_count;
$$;Was dieses Setup richtig macht
- Vector + Relational in einer DB – keine separate Pinecone/Weaviate-Infrastruktur.
- RLS greift automatisch – der Agent kann technisch nicht mehr sehen als der User.
- dbt-Doku = Agent-Kontext – Spaltenbeschreibungen werden zur Tool-Description.
- Klare Tool-Grenzen – Similarity Search (operational) vs. Metrics (analytical) sind getrennt, der Agent muss nicht „SQL können".
TL;DR
Das DWH der 2010er war eine Bibliothek für Analysten. Der Data Stack der AI-First Welt ist eher ein Nervensystem für Agenten: schneller, semantischer, sicherer pro Zeile – und bewusst auf zwei Schichten verteilt statt in ein einziges großes Warehouse gepresst.








