ADR-002: Convex als Backend
Warum sich Owlat für Convex und gegen PostgreSQL und Firebase entschieden hat — wegen Echtzeit-Reaktivität, mitverorteter TypeScript-Logik und Skalierung ohne Konfigurationsaufwand.
- Status: Angenommen
- Datum: 2024-06-15
Kontext
Owlat braucht ein Backend, das Echtzeit-Updates der Oberfläche unterstützt (Zusammenarbeit im E-Mail-Editor, Live-Kampagnenstatistiken), komplexe Abfragen bewältigt (Segmentauswertung, Kontaktfilterung) und ohne Infrastrukturverwaltung skaliert.
Die wichtigsten betrachteten Optionen:
- Klassische REST-API + PostgreSQL — volle Kontrolle, erfordert aber das Betreiben von Servern, das Schreiben einer Echtzeit-Synchronisierung (WebSockets), den Aufbau einer ORM-Schicht und den Umgang mit Migrationen.
- Firebase/Firestore — Echtzeit ab Werk, aber eingeschränkte Abfragemöglichkeiten, keine Mitverortung serverseitiger Logik und Vendor-Lock-in bei schwächerer TypeScript-Unterstützung.
- Convex — Echtzeitfähige Serverless-Datenbank mit TypeScript-Funktionen, die beim Schema mitverortet sind, automatischer Reaktivität und ACID-Transaktionen.
Entscheidung
Convex als Backend-Plattform verwenden. Sämtliche serverseitige Logik liegt in apps/api/convex/ als TypeScript-Funktionen (Queries, Mutations, Actions und Crons).
Konsequenzen
Ermöglicht:
- Echtzeit-Reaktivität ohne WebSocket-Boilerplate — UI-Komponenten abonnieren Queries und aktualisieren sich automatisch
- Durchgängiges TypeScript vom Schema bis zur API — die Schemadefinition erzeugt typisierte Dokument-Interfaces
- Mitverortete Serverlogik — Queries, Mutations und Crons liegen direkt neben dem Schema, auf dem sie arbeiten
- Eingebautes Scheduling (Crons) für wiederkehrende Aufgaben wie Kampagnenversand und Aufräumarbeiten
- Automatische Skalierung — kein Server-Provisioning, keine Verwaltung von Connection Pools
- ACID-Transaktionen über mehrere Tabellen hinweg ohne manuelles Transaktionsmanagement
Trade-offs:
- Abhängigkeit vom Anbieter Convex — eine Migration ist schwieriger als bei einem gewöhnlichen PostgreSQL-Setup
- Die Abfragesprache ist Convex-spezifisch (kein SQL) — neue Mitwirkende müssen die Convex-API lernen
- Kein direkter SQL-Zugriff für komplexe analytische Abfragen — die Segmentauswertung erfordert eigene Logik in
conditions/segmentMatch.ts - Grenzen der Funktionsausführung (Zeit, Speicher) schränken Batch-Operationen ein — große Importe müssen über
integrationImports/in Blöcke zerlegt werden - Die lokale Entwicklung erfordert einen Convex-Account und ein aktives Deployment (kein vollständig offline nutzbarer Modus)