Definition of Done für Bugfixes: praktische Checkliste
Nutze eine klare Definition of Done für Bugfixes, um sicher auszuliefern: Repro-Schritte, Tests, Rollout-Notizen und was du nach dem Release beobachten solltest — in einer einfachen Checkliste.

Was „done“ für einen Bugfix bedeutet (in einfachen Worten)
Ein Bug ist nicht „done“, wenn der Code kompiliert oder wenn er auf einem Laptop funktioniert. „Works on my machine“ bedeutet meistens, dass der Test zu eng war, das Setup anders, oder ein Randfall übersehen wurde. Reale Nutzer benutzen nicht exakt denselben Browser, dieselben Daten, dasselbe Netzwerk oder dieselben Berechtigungen wie du.
Ein Ticket zu früh zu schließen ist der Grund, warum kleine Probleme größer werden: Support-Tickets schießen hoch, das Team verliert Vertrauen in Releases und schnelle Patches häufen sich aufeinander. Die eigentlichen Kosten sind oft nicht der ursprüngliche Bug, sondern die Zeit, die damit verloren geht, das gleiche Problem erneut zu verstehen und das Chaos aufzuräumen.
Bei einem Bugfix sollte „done“ vier Dinge bedeuten: verifiziert, sicher, beobachtbar und erklärbar.
- Verifiziert: Du kannst den Bug zuverlässig reproduzieren und zuverlässig zeigen, dass er weg ist.\n- Sicher: Du hast Datenverlust, Sicherheit und unbeabsichtigte Nebenwirkungen bedacht.\n- Beobachtbar: Du weißt, worauf du nach dem Release achten musst und was einen Rollback rechtfertigt.\n- Erklärbar: Jemand anderes kann das Ticket lesen und verstehen, was passiert ist, was geändert wurde und warum.
Ein einfaches Beispiel: Der Checkout-Total ist nur für zurückkehrende Nutzer mit alten Gutscheinen falsch. Wenn du nur mit einem neuen Account testest, hast du für die tatsächlich Betroffenen nichts „repariert“.
Bevor du Code anfasst: Bestätige den Bug und seine Auswirkungen
Viele „Quick Fixes“ scheitern, weil das Team das falsche Problem behebt. Trenne, was der Nutzer sieht (das Symptom), von dem, was du für die Ursache hältst. Das Symptom ist eine Tatsache. Die Ursache ist eine Vermutung, bis du sie beweist.
Schreib den Impact auf, bevor du den Editor öffnest. Wenn dieser Bug einmal im Monat bei einem Nutzer auftritt, gehst du anders damit um als bei einem Bug, der heute Neuregistrierungen blockiert. Severity ist nicht „wie schlimm es sich anhört“, sondern wie viele Menschen betroffen sind, wie oft und was sie nicht tun können.
Erfasse den genauen Kontext. Viele Bugs sind nur in einer bestimmten Umgebung real: eine bestimmte Browserversion, ein Mobilgerät, eine Staging-Datenbank oder ein neues Release. Wenn du nicht benennen kannst, wo es auftritt, kannst du nicht sicher sagen, dass es behoben ist.
Eine kurze Pre-Code-Checkliste, die du in ein Ticket einfügen kannst:
- Symptom: was der Nutzer sieht, in seinen Worten
- Scope: wer betroffen ist und wie oft
- Umgebung: App-Version, Gerät, Browser/OS und Kontotyp
- Erwartetes Verhalten: was stattdessen passieren sollte
- Ein-Satz-Problemstatement: „Wenn X, passiert Y, aber es sollte Z passieren.“
Beispiel: Ein Gründer sagt „Login ist kaputt.“ Du reproduzierst es und stellst fest, dass es nur auf Safari nach einem Passwort-Reset fehlschlägt. Das ändert die Arbeit. Du reparierst nicht „den Login“ allgemein, sondern einen spezifischen Session- oder Cookie-Flow.
Repro-Schritte, die den Bug wirklich reproduzieren (eine einfache Vorlage)
Ein Bug-Report ist nur nützlich, wenn jemand anderes den Bug ebenfalls auslösen kann. Wenn deine Repro-Schritte nur für die Person funktionieren, die ihn gefunden hat, ist er schwer zu beheben und noch schwerer zu bestätigen, dass er wirklich weg ist.
Schreibe die Schritte so, als würde ein neues Teammitglied ihnen ohne Rückfragen folgen. Entscheidend ist der Startzustand: wer der Nutzer ist, welche Daten existieren und welche Umgebung du verwendet hast.
Eine einfache Repro-Vorlage
Benutze diese Vorlage und fülle sie mit realen Details (nicht Platzhaltern):
Title: <short, specific>
Environment: <prod/staging/local>, <browser/app version>, <device>
Starting state: <logged in/out>, <account role>, <sample record id>, <feature flags>
Steps to reproduce:
1) ...
2) ...
3) ...
Expected result: ...
Actual result: ...
Evidence: <error message>, <log snippet>, <screenshot description>
Frequency: <always / 3 out of 10>, Triggers: <only after refresh, only on slow network>
Wann immer möglich, füge den exakten Fehltext bei. „Login fails“ ist vage, aber „400: invalid_grant after password reset“ gibt dem Fixer einen echten Anhaltspunkt.
Wenn das Problem flaky ist, sag das und beschreibe, was es anscheinend auslöst. Nenne Timing, Gerätetyp, Browser-Erweiterungen oder jede kürzliche Änderung (neuer Nutzer, importierte Daten, Upgrade des Plans).
Mach einen Schnell-Check, indem du deine Schritte jemand anderem gibst. Wenn die Person nicht innerhalb von 5 Minuten reproduzieren kann, braucht der Report noch eine Überarbeitung.
Akzeptanzkriterien: woran du erkennst, dass es behoben ist
Akzeptanzkriterien sind die gemeinsame Antwort auf: „Was soll nach dem Deploy passieren?“ Bei Bugfixes verwandeln sie „ich glaube, es ist behoben“ in „wir können beweisen, dass es behoben ist“.
Beschreibe in klaren, testbaren Begriffen, wie „gut“ aussieht. Beziehe es auf das Nutzerergebnis, nicht die Implementierung. Beispiel: „Der Nutzer kann sich mit korrektem Passwort einloggen und wird innerhalb von 2 Sekunden zum Dashboard geleitet.“
Nenne dann die Randfälle, die oft übersehen werden: Leere Zustände, Timeouts, fehlerhafte Eingaben, Retries und partielle Fehler.
Eine einfache Checkliste, die du kopieren kannst:
- Primärer Pfad funktioniert Ende-zu-Ende
- Bekannte Randfälle sind behandelt (leere Eingabe, ungültige Werte, langsames Netzwerk, Retry)
- Keine neuen Fehler in den Logs und keine neuen Warnungen in der UI für denselben Flow
- UI-Verhalten ist klar (Meldungen, Button-Zustände, Ladeindikatoren, Weiterleitungen)
- Daten bleiben korrekt (keine Duplikate, keine partiellen Writes, keine überraschenden Löschungen)
Füge Non-Goals hinzu, um Scope-Creep zu verhindern. Beispiel: „Wir ändern in diesem Fix nicht die Passwort-Policy“ oder „Wir redesignen die Login-Seite nicht, nur die Fehlerbehandlung.“
Wenn der Fix Text oder Verhalten ändert, schreib es auf. „Falsches Passwort“ vs. „E-Mail nicht gefunden“ ist nicht nur eine Wortwahl — das kann Support-Last und Sicherheitsrisiken verändern.
Wenn möglich, hol dir eine schnelle Zustimmung vom Anforderer. 2 Minuten Bestätigung sparen oft einen Tag Nacharbeit.
Ein Schritt-für-Schritt-Workflow, um einen Bug sicher zu schließen
Ein guter Close dreht sich weniger um die Code-Änderung und mehr darum zu beweisen, dass der Bug weg ist, ohne einen neuen zu schaffen.
-
Reproduzieren und Beweismaterial sichern. Screenshot, exakter Fehltext und Umgebung (App-Version, Browser/Gerät, Nutzerrolle, Feature-Flag-Status). Wenn du es nicht reproduzieren kannst, straffe den Report, bevor du rätst.
-
Isoliere die kleinste wahrscheinliche Ursache. Finde die eine Bedingung, die das Verhalten umschaltet (ein Input, ein Account-Status, eine API-Antwort). Das verhindert „Fixes“, die nur zufällig funktionieren.
-
Mache die kleinste sichere Änderung. Vermeide Refactorings während eines Bugfixes, außer das Durcheinander ist die Ursache. Kleine Änderungen sind einfacher zu reviewen, zu testen und zurückzunehmen.
-
Verifiziere an zwei Orten. Teste lokal und anschließend in einer sauberen Umgebung, die der Produktion möglichst ähnlich ist.
Eine kurze Closure-Checkliste fürs Ticket:
- Repro bestätigt und Beweise gespeichert
- Root Cause in einem Satz beschrieben
- Minimale Änderung vorgenommen (und warum sie sicher ist)
- Lokal und in einer sauberen Umgebung verifiziert
- Notizen hinzugefügt: was geändert wurde, was nicht und Risikobereiche
Füge schließlich Rollout- und Monitoring-Notizen hinzu: wie der Deploy sicher durchgeführt wird, welche Metriken oder Logs sich verbessern sollten und was einen Rollback bedeutet (z. B. ein Anstieg von 500-Errors oder Login-Fehlern in der ersten Stunde).
Tests: was hinzuzufügen, was erneut auszuführen ist und was dokumentiert werden muss
Ein Bug ist erst wirklich done, wenn die Tests dieselbe Geschichte erzählen wie deine Repro-Schritte. Versuche, mindestens eine automatisierte Prüfung zu hinterlassen, die vorher fehlgeschlagen wäre und jetzt besteht.
Füge oder aktualisiere einen Test, der dem realen Fehler entspricht. Halte ihn klein und fokussiert, damit er lesbar bleibt und nicht flaky wird. Decke den Happy Path ab und füge einen Randfall hinzu, der zeigt, wie der Bug durchgerutscht ist (fehlendes Feld, Timing-Problem, veralteter Cache, seltener Benutzerwert).
Nachdem der gezielte Test besteht, mache eine kurze Regression rund um angrenzende Flows, die du berührt haben könntest:
- Die Hauptnutzerreise, die den geänderten Code enthält
- Einen angrenzenden Flow (z. B. Signup, wenn du Login gefixt hast)
- Einen Basis-Permissions-Check (authorisiert vs. nicht autorisiert)
- Bei UI-Fixes: Verifizieren auf zwei tatsächlich unterstützten Browsern/Geräten
- Bei Backend-Fixes: Einen fehlerhaften Input testen, der sauber fehlschlagen soll
Dokumentiere, was du ausgeführt hast und was nicht. Wenn du eine Testlücke akzeptierst, benenne sie und erkläre warum (Zeit, Tooling, fehlende Fixtures, unklare Anforderungen) sowie was sie später auffangen würde (Monitoring-Alert, Folgeaufgabe, manuelle Checkliste).
Beispiel: Wenn ein Login-Fix Token-Parsen betraf, füge einen Test für ein gültiges Token und einen für ein fehlerhaftes Token hinzu, das einen sauberen Fehler ohne Leakage von Secrets zurückgeben muss.
Safety-Checks: Sicherheits- und Datenrisiken ausschließen
Ein Bug kann „repariert“ sein und trotzdem ein größeres Problem verursachen: ein Datenleck, eine Bypass-Möglichkeit bei Berechtigungen oder Logs voller sensibler Infos. Das ist der Teil, den Leute beim Eilen überspringen.
Überprüfe Änderungen rund um Inputs, Auth und alles, was die Datenbank berührt. Viele Incidents entstehen durch kleine Editen wie „parameter hinzufügen“ oder „mehr loggen zum Debuggen“.
Bevor du das Ticket als erledigt markierst:
- Secrets: Stelle sicher, dass keine API-Keys, Tokens oder Zugangsdaten in Code, Config, Error-Messages oder Client-Bundles gelandet sind.\n- Input-Handling: Validieren und säubern von Eingaben, besonders dort, wo sie in Queries, Filtern oder Sortierungen verwendet werden. Nutze sichere Query-Muster, um SQL-Injection zu vermeiden.\n- Auth und Berechtigungen: Prüfe erneut, ob der gefixte Pfad weiterhin Login- und Rollenprüfungen durchsetzt (und dass Error-Handling sie nicht versehentlich umgeht).\n- Logging: Achte darauf, dass Logs keine Passwörter, Session-Tokens, Reset-Links oder personenbezogenen Daten enthalten. Wenn Kontext nötig ist, logge eine ID, nicht den Rohwert.\n- Abuse-Fälle: Wenn ein Endpoint oder Flow geändert wurde, überlege Rate Limiting und Brute-Force-Szenarien (Login, Passwort-Reset, Promo-Codes, OTPs).
Ein konkretes Beispiel: Du behebst einen Login-Bug, indem du die Fehlermeldung „hilfreiche Details“ hinzufügst (z. B. ob eine E-Mail existiert). Das ermöglicht Account-Enumeration. Bevorzuge eine generische Meldung und halte Details intern.
Stell dir ein paar finale Fragen, bevor du schließt:
- Könnte diese Änderung Daten dem falschen Nutzer offenlegen?\n- Macht sie es leichter, Accounts, Tokens oder Passwörter zu erraten?\n- Könnten neue Logs sensible Informationen leaken?\n- Könnte ein Bot das schneller treffen als ein Mensch?
Rollout-Notizen: was du schreiben solltest, damit Releases niemanden überraschen
Rollout-Notizen sind das „Heads up“, das eine Code-Änderung in ein sicheres Release verwandelt. Sie lassen jemanden, der nicht am Bug gearbeitet hat, verstehen, was sich geändert hat, wie es ausgeliefert wird und was zu tun ist, wenn etwas schiefgeht.
Beginne mit einer kurzen Zusammenfassung für Nicht-Techniker: was kaputt war, was Nutzer jetzt bemerken und wer betroffen ist. Wenn der Bug Abrechnung, Login oder Berechtigungen betroffen hat, sag das deutlich.
Erfasse dann die Deploy-Risiken:
- Config-Änderungen (neue Env-Var, geänderter Wert, Secret-Rotation)\n- DB-Migrationen (was läuft, wie lange es dauern kann)\n- Feature-Flags (Name, Default-State, wer toggeln kann)\n- Rollout-Plan (all-at-once, Canary, schrittweise nach % oder Region)\n- Rollback-Plan (was revertiert wird und wie du verifizierst)
Sei spezifisch bei Rollback-Triggern. „Rollback jetzt“ sollte etwas Beobachtbares bedeuten, z. B. ein Anstieg von Login-Fehlern, ein Sprung in Support-Tickets oder ein klarer neuer Fehler in den Logs. Notiere, ob ein Rollback bei Migrationen sicher ist (einige Schema-Änderungen sind nicht einfach umkehrbar).
Liste außerdem kundenseitige Änderungen, auch kleine: UI-Text, E-Mails, Benachrichtigungen oder Fehlermeldungen. Support-Teams brauchen das.
Beispiel: „Login-Fix verbessert Session-Handling für Legacy-User auf Safari. Keine DB-Änderungen. Neue Env-Var für Timeout des E-Mail-Providers. Rollout: 10 % für 30 Minuten, dann 100 %, wenn Sign-In-Erfolg normal bleibt. Rollback bei Anstieg von Sign-In-Fehlern über Baseline.“
Nach dem Release: was zu überwachen ist und wie lange
Ein Bug ist nicht done, wenn der Code gemerged ist. Er ist done, wenn die Änderung sich in der realen Welt unter realem Traffic bewährt hat.
Setze ein Watch-Window für jedes Release. Bei Low-Risk-Fixes sind 2–4 Stunden oft ausreichend. Für alles, was Auth, Zahlungen oder Daten betrifft, plane 24–72 Stunden. Nenne einen Owner für das Fenster (nicht „das Team“) und stelle sicher, dass diese Person rollen oder hotfixen kann.
Konzentriere dich auf Signale, die Kundenschmerz schnell zeigen:
- Error-Rate und Top-New-Errors (nach Endpoint oder Screen)\n- Latenz und Timeouts (p95 sagt oft mehr als Durchschnittswerte)\n- Sign-in-Fehler und Passwort-Reset-Fehler\n- Payment-Fehler und Checkout-Abbrüche\n- Support-Tickets und Nutzerbeschwerden (sie zählen als Monitoring)
Definiere Schwellenwerte, die Aktion auslösen, bevor du shipped, damit es später keinen Streit gibt. Beispiele: „Login-Fehler 2x Baseline für 10 Minuten“ oder „ein neuer Fehler in den Top-5“. Kombiniere Alerts mit einer einfachen Reaktion: untersuchen, roll back oder Rollout pausieren.
Achte auch auf leise, aber gefährliche Änderungen: weniger abgeschlossene Logins, weniger erstellte Projekte, mehr Retries. Das kann bedeuten, dass der Bug sich verschoben hat, statt verschwunden zu sein.
Dokumentiere, was du geprüft hast und das Ergebnis: Zeitfenster, Dashboards/Logs, Anstiege und die abschließende Entscheidung.
Häufige Fallen, die „gefixte“ Bugs zurückbringen
Wiederkehrende Bugs sind meist kein Zufall. Sie passieren, wenn ein Fix ohne Beweise und Kommunikation shipped wurde, die eine Änderung in ein verlässliches Ergebnis verwandeln.
Eine häufige Fehlerquelle ist, das Ticket zu schließen ohne saubere Repro- und klare Akzeptanzkriterien. Wenn du den Bug nicht auf Abruf zeigen kannst, kannst du nicht sicher sein, dass er weg ist oder dass du das richtige Problem gelöst hast.
Ein weiterer Fehler ist, das Symptom zu beheben und die Root Cause zu überspringen. Beispiel: Einen Retry-Button hinzufügen für eine fehlerhafte Anfrage, obwohl das eigentliche Problem ein abgelaufenes Token ist, das nie erneuert wird. Der Retry kaschiert das Problem und trainiert Nutzer, weiterzuklicken.
Die Fallen, die Fixes am häufigsten aufheben:
- Keine reproduzierbaren Schritte oder vages „works for me“-Checking\n- Kein Test hinzugefügt (oder der falsche), sodass eine spätere Änderung den Bug still wieder einführt\n- Ein „kleiner Fix“, der heimlich ein großes Refactor einschmuggelt und Review-Risiko erhöht\n- Rollout-Notizen übersprungen, sodass Support und Kolleg:innen nicht wissen, was sich geändert hat\n- Nur den Happy Path verifiziert, nicht in einer realistischen Umgebung
Der letzte Punkt verdient besondere Aufmerksamkeit. Ein Fix kann lokal durchgehen, aber in Staging fehlschlagen wegen realer Daten, fehlender Env-Variablen, Caching oder abweichender Auth-Settings. Teste immer mit einem frischen Account, einer sauberen Browser-Session und dem langsamsten/ältesten Gerät, das du vernünftigerweise testen kannst.
Beispiel: Einen Login-Bug schließen, ohne die Produktion zu brechen
Szenario: Nach einem KI-generierten Update melden einige Nutzer Sign-In-Probleme. Für den Entwickler funktioniert es, für echte Kunden nicht.
Schlechte Repro-Schritte: „Login ist manchmal kaputt.“ Das verschwendet Stunden, weil niemand den Fehler zuverlässig sieht.
Gute Repro-Schritte sind spezifisch und wiederholbar:
- Verwende einen bestehenden Nutzer, der vor dem letzten Release erstellt wurde.\n2. Logge dich aus und versuche, dich auf Mobile Safari einzuloggen.\n3. Gib korrekte E-Mail und Passwort ein.\n4. Beobachte: Nach Absenden lädt die Seite neu und du bist weiterhin ausgeloggt (keine Fehlermeldung).
Akzeptanzkriterien sollten ebenso klar sein. Schlecht: „Users can log in again.“ Besser: „Der Nutzer kommt zum Dashboard, erhält ein Session-Cookie und bleibt nach Refresh eingeloggt. Falsche Passwörter zeigen weiterhin die gleiche Fehlermeldung wie zuvor.“
Für Tests: Füge einen fokussierten Check hinzu und führe eine Regression aus:
- Integrationstest für den Sign-In-Flow (korrekte Credentials erzeugen eine Session und liefern Erfolg).\n- Regression: Passwort-Reset, Logout und Sign-In im selben Browser, der zuvor fehlgeschlagen ist.
Rollout-Notizen können kurz, aber konkret sein: „Fixes session handling for legacy users on Safari. No DB changes. If issues appear, roll back to prior build and invalidate sessions.“ (Behalte englische Tech-Details wie hier, wenn sie klarer sind.) Nach dem Deploy: beobachte Login-Error-Rate, neue Session-Erstellung und Support-Tickets für 24–48 Stunden.
Das Ticket ist wirklich done, wenn der Bug sich vor dem Fix reproduzieren ließ, nach dem Fix nicht mehr reproduzierbar ist, Tests den Fehler abdecken und Rollout-Notizen sagen, was sich geändert hat und worauf zu achten ist.
Nächste Schritte: Mach das zur Regel und hol dir Hilfe, wenn nötig
Mach das zur Gewohnheit, indem du es an einem Ort festhältst, wo jeder Bug lebt (Ticket-Template, ein geteiltes Doc oder ein Formular) und dort die einseitige „Definition of Done“ einfügst, sodass sich niemand alles merken muss.
Macht eine kurze Team-Session, um euch darauf zu verständigen, was „done“ bedeutet. Leise Unterschiede sind wichtig: Die eine Person denkt „Repro + Fix“ reicht, die andere erwartet Tests, Rollout-Notizen und einen Post-Release-Watch-Plan. Einmalige Abstimmung verhindert Wiederöffnungen.
Probiere die Checkliste bei den nächsten drei Bugfixes und passt sie an, was sich schwer oder unklar anfühlt. Halte sie kurz, aber nicht verhandelbar.
Eine einfache Starter-Checklist, die du ins Bug-Template kopieren kannst:
- Repro-Schritte bestätigt (und gespeichert), plus Erwartet vs. Tatsächlich\n- Akzeptanzkriterien in einfacher Sprache\n- Tests hinzugefügt oder aktualisiert, und wichtige bestehende Tests erneut ausgeführt\n- Rollout-Notizen vorbereitet (Risiko, wer zu benachrichtigen ist, Rollback-Plan)\n- Post-Release-Watch-Plan (was zu überwachen ist und wie lange)
Wenn Bugs trotz Befolgung dieser Dinge wieder auftauchen, ist die Root Cause oft architektonisch oder sicherheitsbezogen, nicht eine einzelne Codezeile. Wenn du einen KI-generierten Codebase von Tools wie Lovable, Bolt, v0, Cursor oder Replit geerbt hast, kann FixMyMess (fixmymess.ai) ein kostenloses Code-Audit durchführen, um Probleme wie gebrochene Authentifizierung, exponierte Secrets oder verhedderte Logik vor deinem nächsten Release aufzuspüren.