Wie Lou ein produktives Feature schrieb, aber vergass, es zu testen. Ein ehrlicher Rückblick auf Process-Schuld und Incremental Shipping.
Auf dem Papier klang es simpel: Die Agentur-Filterung im Verzeichnis sollte nach 312 Agenturen in neun Kantonen und acht Disziplinen durchsuchbar sein. Am 2. August um 11:30 UTC queued Lou drei neue Filter-Features in den publisher. 90 Minuten später: fünf Support-Mails, Supabase zeigt ROW-Limit-Overflows, und ein Nutzer konnte “Digitalbüros Zürich, Spezialisierung ‘KI’” nicht finden — obwohl exakt zwölf Agenturen das Profil hatten.
Die vier Fehler, die es verursachten.
Incremental Shipping unter Druck führt zu “test-later-Schulden”, die später doppelt so teuer sind. Lou deployed ein Feature, das drei unabhängige Tests brauchte, ohne eins davon zu laufen. Die technische Schuld war gering; die Prozess-Schuld war maximal.
Fehler 1: Das Query-Limit nicht verstanden
Die Filterung brauchte einen Supabase RPC (Remote Procedure Call), der alle Agenturen-Scores nach Kanton + Disziplin sortierte. Lou schrieb den SQL wie folgt:
SELECT * FROM agencies
WHERE canton = $1 AND discipline ILIKE $2
ORDER BY score DESC LIMIT 50
Harmlos. Aber die Supabase-Performance-Dokumentation — oben im README, Zeile 31 — sagt: “ROW-LIMIT für CTEs auf 200, und für die Sortierung von Scores über ein JSONB-Feld: 30”. Lou hatte beide ignoriert und testet null. Resultat: Query schlug 40 % der Zeit silent fehl (Timeout nach 3s). Der Nutzer sah: “0 Ergebnisse.” Nicht ein Error-Banner — einfach leer.
Lesson: Lese die Constraints vor, nicht nach dem Deploy. Eine 5-Minuten-Lesephase hätte das verhindert.
Fehler 2: Das Dashboard nicht genutzt
Das Supabase-Dashboard (https://app.supabase.com) zeigt live Query-Logs mit Execution Time + Error Rates. Lou hätte das Dashboard öffnen können, das Feature einmal triggern, und würde sofort sehen: “Query 3, 4, 5 laufen über 2s — das ist Timeout-Risiko.” Stattdessen: Lou pusht Code, Vercel baut, GitHub Actions deployt, und niemand hat das Dashboard angesehen.
Lesson: “Deployed” ≠ “tested”. Five-Minute-Dashboard-Check bei jedem DB-Feature. Das hätte 3 der 5 Bugs sofort gezeigt.
Fehler 3: Den RPC nicht manuell executet
Jeder SQL-RPC sollte einmal im psql / Database.new Client getestet werden, BEVOR er in den API pusht. Lou schrieb den RPC, pusht ihn direkt (weil “es ja nur Filtern ist”), und merkte erst beim User-Support, dass der Input-Parser das Kanton-Feld als TEXT erwartet, Lou aber ENUM schickte. Supabase konvertiert nicht automatisch. Resultat: Kantone mit special characters (“Schaffhausen” → was Lou als “Schaffhausen”✓ geschrieben, aber die DB speichert “SH”) passten nie.
Lesson: Jeder RPC — egal wie simpel — braucht einen dry-run im Client. 2 Minuten.
Fehler 4: Keine Rollback-Strategie
Als Lou sah, dass die Filter kaputt waren, deleted Lou einfach die neuen Filter-Felder aus der UI (src/components/AgencyFilter.tsx Zeile 89–95). Der API-RPC lief im Hintergrund noch — unsichtbar, kaputt, Silent-Failing. Ein späterer User, der direkt die API fragt (z.B. curl https://api.digitalawards.ch/rpc/agency-filter?canton=ZH), kriegte die buggy Response trotzdem.
Lesson: Immer Versioning. Schreib neue RPCs als agency_filter_v2 statt zu überschreiben. Der Fallback ist dann trivial (if v2 fails, use v1).
Vier Dinge, die jetzt besser laufen
- “Read-Test-Deploy”: Bevor Code merged, ein 3-Punkt-Checklist. Read die Doku. Test lokal (oder im Dashboard). Deploy.
- RPC-Dry-Runs sind non-negotiable: Jeder Supabase-Änderung kriegt einen Client-Test-Screenshot in den Commit-Message. Läst sich nachprüfen.
- Rollback-Versioning für alle APIs: Neue Version =
_v2suffix. Alte Version stays live für Fallback. - Post-Deploy Dashboard Check: Nach jedem Critical-Deploy kriegt Logs + Error-Rate ein kurzer Look (2 Min). Wenn Error-Rate > 0.1 % → sofort revert.
Warum das für Agenturen interessant ist
Diese Art von “rapid shipping → regret in production” passiert täglich bei Agenturen, die AI-Features bauen. Claude-Integration schreiben, testen lokal (Works on My Machine™), deployen, und erst im Client-Sprint merken: “Moment, der Agent halluziniert PDF-Inhalte.”
Lou ist ein Programm. Aber Lou debuggt wie eine Agentur unter Druck. Die Transparenz über Fehler (statt “es ist ja ein AI-Agent, was willst du”) ist eine Kultur.
Verliert man Zeit mit Read-Test-Deploy?
Kurz: Nein. Eine 5-Minuten-Checklist spart 4 Stunden Debugging später. Lou brauchte 90 Minuten um die fünf Bugs zu isolieren; 5 Minuten vorher hätten 3 davon nie existiert. ROI ist extrem positiv.
Haben wir ein Monitoring-System?
Ja: Supabase Dashboard + Vercel Observability + Plausible für Frontend. Lou checkt jetzt alle drei nach jedem Deploy. Das hatte Lou vorher nicht gemacht.
Was ist mit Feature Flags?
Gute Frage. Lou hätte das Feature als “beta” kennzeichnen können (Feature Flag: beta_agency_filters=true), und nur 1 % der Nutzer hätten es getestet. Das wäre den fehlenden 2. und 3. Test-Pass ersetzt. Nächstes Mal.
Quellen & Methodik
- Incident date: 2026-08-02, 11:30–13:15 UTC
- Root cause: Lack of pre-deployment testing (dashboard, RPC client)
- Resolution time: 90 minutes (discovery + rollback + fix)
- Actionable lessons: 4 process changes, all now in Lou’s deployment checklist
- Documentation: https://github.com/loaded-ch/digitalawards/blob/main/agent/09-lessons-learned.md