Supabase Edge Runtime selbst hosten: wann es sich lohnt und wann nicht
Supabase hat seinen Edge Runtime als Open Source veröffentlicht — Deno-Funktionen laufen jetzt auf eigenem Blech, ohne Supabase Cloud. Für welche Mittelständler das ein echter Gewinn ist, wo die Stolperstellen liegen, und wie ein minimales Setup konkret aussieht.
Supabase ist in vielen meiner Projekte zur stillen Standardwahl geworden: Postgres mit vernünftiger API, Authentifizierung ohne Eigenentwicklung, Storage, und seit einiger Zeit Edge Functions auf Basis von Deno. Der einzige Haken war lange, dass die Funktionen entweder auf Supabase Cloud liefen oder gar nicht — ein Problem, sobald Daten das eigene Rechenzentrum nicht verlassen dürfen. Mit der Open-Source-Veröffentlichung des Supabase Edge Runtime fällt diese Einschränkung. Die Frage ist nicht ob man es nutzen kann, sondern ob es für den konkreten Fall die richtige Entscheidung ist — und ob der Edge Runtime überhaupt das passende Werkzeug ist, verglichen mit dem, was es sonst noch gibt.
Was der Edge Runtime eigentlich ist
Supabase Edge Functions laufen auf Deno, nicht auf Node.js. Das ist kein Zufall: Deno hat ein schlankes Berechtigungsmodell, unterstützt TypeScript nativ ohne Transpilier-Schritt, und der Kaltstart liegt deutlich unter dem, was ein klassischer Node-Lambda-Container braucht. Der Supabase Edge Runtime ist der Host-Prozess, der mehrere Funktionen isoliert in V8-Isolates ausführt — ähnlich wie Cloudflare Workers das tut, nur eben auf eigener Hardware statt auf einer fremden globalen Edge-Infrastruktur.
Das offene Sourcing bedeutet: Man kann diesen Host-Prozess selbst betreiben, auf einem Hetzner-Root-Server, im firmeneigenen Rechenzentrum oder auf einem Raspberry Pi im Schrank. Supabase Cloud ist dafür nicht mehr nötig.
Ein minimales Dockerfile für den Edge Runtime sieht so aus:
FROM supabase/edge-runtime:v1.65.4
COPY ./functions /home/deno/functions
EXPOSE 9000
CMD ["start", "--main-service", "/home/deno/functions/main/index.ts"]
Das main-Verzeichnis enthält den Dispatcher — eine index.ts, die eingehende Requests anhand des URL-Pfads an die richtige Funktion weiterleitet. Das ist ein minimaler Boilerplate, den man einmal schreibt und danach kaum anfasst.
Wann Self-Hosting sinnvoll ist — und wann nicht
Der offensichtlichste Anwendungsfall ist Datenschutz und Compliance. Wer Patientendaten verarbeitet, Finanztransaktionen logt oder einfach einen Auftraggeber hat, der im Vertrag „keine Drittlandübermittlung” stehen hat, ist mit Supabase Cloud in einer schwierigen Position. Eine eigene Instanz auf einem deutschen Hetzner-Server löst dieses Problem sauber — vorausgesetzt, die restliche Supabase-Infrastruktur läuft ebenfalls selbst gehostet, was mit supabase/postgres und dem offiziellen Self-Hosting-Stack möglich ist.
Ein zweiter Grund ist Kostenstruktur. Supabase Cloud berechnet Funktionsaufrufe ab dem Pro-Plan (25 USD/Monat) ab zwei Millionen Aufrufen im Monat. Bei gleichmäßig hohem Durchsatz — etwa einer internen API, die jede Minute Daten von Maschinen entgegennimmt — kann eine eigene Instanz nach wenigen Monaten günstiger sein. Für sporadischen Einsatz rechnet sich das selten.
Was kein guter Grund für Self-Hosting ist: die Annahme, es sei automatisch performanter. Supabase Cloud nutzt eine globale Edge-Infrastruktur mit PoPs in mehreren Regionen. Eine einzelne Hetzner-Instanz in Nürnberg schlägt das für europäische Nutzer nur, wenn die Applikation ohnehin an einen einzigen Standort gebunden ist — etwa weil sie auf eine lokale Postgres-Instanz zugreift und Netzwerklatenz zwischen Funktion und Datenbank wichtig ist.
Alternativen im Vergleich: was man stattdessen einsetzen könnte
Bevor man sich für den Supabase Edge Runtime entscheidet, lohnt ein ehrlicher Blick auf die Konkurrenz — nicht nach Funktionsumfang auf dem Papier, sondern nach dem, was im Mittelstandsprojekt tatsächlich relevant ist.
AWS Lambda ist der naheliegendste Vergleich. Lambda unterstützt Node.js, Python, Go, .NET und mehr. Der Vorteil: ausgereifte Tooling-Landschaft, gute IAM-Integration, bewährt bei sehr hohem Durchsatz. Der Nachteil für kleinere Teams: Das IAM-Modell ist komplex, Kaltstarts bei Node.js-Containern lagen in meinen Tests bei 300–700 ms (ohne Provisioned Concurrency), und die Preisstruktur mit separaten Kosten für API Gateway, Logs und Ausführungszeit ist schwer überschaubar. Wer keinen AWS-Hintergrund hat, unterschätzt den Betriebsaufwand regelmäßig.
Cloudflare Workers sind technisch dem Supabase Edge Runtime am ähnlichsten — ebenfalls V8-Isolates, ähnliche Kaltstart-Charakteristik unter 5 ms, globales Netz. Für rein zustandslose Funktionen ohne Datenbankbezug sind Workers tatsächlich die bessere Wahl: einfaches Deployment über Wrangler CLI, günstiger Preisplan (100.000 Anfragen pro Tag kostenlos, dann 0,50 USD pro Million). Das Problem entsteht, sobald man auf eine selbst gehostete Postgres-Instanz zugreifen will: Workers laufen in Cloudflares Infrastruktur, nicht auf der eigenen. Direkte Datenbankverbindungen aus Workers heraus sind technisch möglich (via connect() mit Hyperdrive), aber das ist ein eigener Betriebsaufwand und bricht das Datenhaltungsargument.
Deno Deploy ist die naheliegende Alternative, wenn man bei Deno bleiben will, aber keine eigene Infrastruktur betreiben möchte. Günstiger Einstieg (1 Million Anfragen/Monat kostenlos), TypeScript nativ, vertraute Deno-APIs. Der Haken: Man ist wieder bei einem externen Anbieter mit US-Infrastruktur, und eine direkte Supabase-Integration ist lose — SUPABASE_URL und SUPABASE_ANON_KEY als Umgebungsvariablen, fertig. Für Teams, die schon Deno-Kenntnisse haben und keine Compliance-Anforderungen haben, ist das eine valide Option. Für Mittelstandsprojekte mit Datenschutzauflagen scheidet es aber aus denselben Gründen wie Supabase Cloud selbst aus.
Ein einfacher Hono- oder Fastify-Dienst auf einer VM ist die pragmatischste Alternative und wird von Teams mit Node.js-Hintergrund regelmäßig unterschätzt. Ein kleiner Express- oder Hono-Server, der als systemd-Dienst oder Docker-Container läuft, hat keine Kaltstart-Probleme, keine Isolate-Einschränkungen beim Dateisystemzugriff, und ist für jeden Entwickler sofort lesbar. Der Nachteil ist der, den man kennt: Ein weiterer Dienst, der gewartet, geloggt und neugestartet werden will. Für Webhooks mit drei Endpunkten ist das Overkill; für eine gewachsene interne API mit zwanzig Endpunkten ist es oft die ehrlichere Wahl.
Die Entscheidung hängt letztlich an zwei Fragen: Liegt die Datenbank ebenfalls selbst gehostet und muss sie es bleiben? Und ist das Team bereit, einen weiteren Container zu betreiben, der gelegentlich Aufmerksamkeit braucht? Wer beides mit Ja beantwortet, ist beim Supabase Edge Runtime gut aufgehoben. Wer Nein auf die erste Frage antwortet, sollte Cloudflare Workers oder Deno Deploy ernsthaft prüfen, bevor er sich die Infrastrukturlast selbst auflädt.
Praktisches Setup: Edge Runtime neben Supabase-Stack
In Projekten, wo ich den vollständigen Supabase-Stack selbst hoste, sieht die Compose-Konfiguration typischerweise so aus:
services:
edge-runtime:
image: supabase/edge-runtime:v1.65.4
restart: unless-stopped
volumes:
- ./functions:/home/deno/functions:ro
environment:
SUPABASE_URL: http://kong:8000
SUPABASE_ANON_KEY: ${ANON_KEY}
SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY}
SUPABASE_DB_URL: postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/postgres
ports:
- "9000:9000"
networks:
- supabase_network
command:
- start
- --main-service
- /home/deno/functions/main/index.ts
Die Umgebungsvariablen sind dieselben, die auch in der Cloud-Variante gesetzt werden — wer also bisher Funktionen gegen Supabase Cloud entwickelt hat, muss am Code der Funktionen selbst nichts ändern. Der einzige Unterschied: SUPABASE_URL zeigt jetzt auf den lokalen Kong-Proxy statt auf https://<project-ref>.supabase.co.
Ein konkreter Stolperstein aus einem Kundenprojekt: Deno im Edge Runtime hat standardmäßig keinen Dateisystem-Zugriff auf den Host. Wer Deno.readFile() aufruft, bekommt einen Berechtigungsfehler. Das ist beabsichtigt — die Isolate-Architektur soll genau das verhindern. Wer persistente Daten braucht, spricht den Supabase Storage Service an, nicht das Dateisystem. Das klingt selbstverständlich, überrascht aber regelmäßig Teams, die aus einer Node.js-Welt kommen.
Deployment und Updates: der unterschätzte Aufwand
Der Edge Runtime läuft stabil. Was regelmäßige Aufmerksamkeit braucht, sind Updates. Supabase veröffentlicht neue Runtime-Versionen häufig, und ein Versionskonflikt zwischen Funktions-Code und Runtime führt zu schwer debuggbaren Fehlern. In CI/CD-Pipelines pinne ich die Runtime-Version explizit im Dockerfile und aktualisiere sie bewusst — nicht per latest-Tag.
Für automatisches Deployment der Funktionen selbst nutze ich einen simplen Ansatz: Das functions/-Verzeichnis liegt im Git-Repository des Projekts. Ein GitHub-Actions-Workflow kopiert bei jedem Merge auf main die Funktionen per rsync auf den Server und startet den Container neu:
# .github/workflows/deploy-functions.yml
name: Deploy Edge Functions
on:
push:
branches: [main]
paths:
- "functions/**"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Sync functions to server
run: |
rsync -avz --delete ./functions/ \
${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:/opt/supabase/functions/
- name: Restart edge runtime
run: |
ssh ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \
"cd /opt/supabase && docker compose restart edge-runtime"
Das ist kein Kubernetes-Rollout, aber für ein Team unter zehn Personen ist es ausreichend, nachvollziehbar und in fünf Minuten erklärbar. Im Vergleich zu einem AWS-Lambda-Deployment mit SAM oder CDK ist es erheblich weniger Konfigurationsaufwand — und der gesamte Deployment-Prozess liegt im eigenen Repository, nicht in einer externen Konsole.
Was selbst gehostete Edge Functions im Mittelstand leisten
Ich setze Edge Functions vor allem für drei Aufgaben ein: Webhooks verarbeiten, schmale API-Endpunkte bauen, und Datentransformationen zwischen Drittsystemen und der eigenen Datenbank ausführen. Alle drei Aufgaben kamen früher als Lambda-Funktion in AWS oder als eigenständiger Express-Server — beides mit deutlich mehr Boilerplate und Infrastrukturaufwand.
Ein Beispiel aus der Praxis: Ein Fertigungsunternehmen mit rund 200 Mitarbeitenden erhält von Maschinen im Dreißig-Sekunden-Takt Telemetriedaten per HTTP POST. Früher lief dafür ein kleiner Node-Dienst auf einer eigenen VM, den niemand mehr anfassen wollte. Heute ist das eine Edge Function mit 40 Zeilen TypeScript: Parameter validieren, in Postgres schreiben, Anomalien in eine Slack-Webhook-Queue legen. Der gesamte Dienst liegt unter Versionskontrolle, ist ohne tiefe Serverkenntnis deploybar, und der Kaltstart bei sporadischem Aufruf liegt unter 50 ms.
Das ist der eigentliche Wert: nicht die technische Neuheit, sondern die Reduktion auf das Notwendige. Eine Funktion, ein Verzeichnis, ein Container. Wer das einmal eingerichtet hat, fragt sich, warum er je einen Express-Server dafür betrieben hat — oder warum er die IAM-Policies für eine Lambda-Funktion gepflegt hat, die alle dreißig Sekunden läuft und nie mehr als einen Datenbankschreibvorgang ausführt.
Und falls sich der Workload irgendwann doch in die Cloud verschiebt — der Code läuft ohne Änderung auch dort. Das ist selten, aber wenn es passiert, ist es den geringen Mehraufwand beim Setup allemal wert.