Das Visitor-Model hält die Variante in einem Boolean-Feld pro Experiment fest, und Conversion-Events wie eine Formularsendung, eine Registrierung oder ein Kauf werden gegen dieselbe Besucher-ID getrackt. Ein Management-Command exportiert die Paare als CSV, und das Produktteam wertet sie in dem Tool aus, das es ohnehin nutzt. Ein Dashboard wurde nicht gebaut und hat niemandem gefehlt.
Leistungen
Backend Engineering, Produkt
Branche
B2B-Marktplatz
Jahr
2022-2024
A/B-Tests in einem Django-Monolithen.
Das Produktteam hatte wochenlang über Features gestritten: ein neues Kontaktformular, eine einfachere Preisanzeige, ein Onboarding-Flow. Niemand konnte belegen, dass die eigene Version besser konvertiert, und jede Änderung bedeutete ein volles Deploy, mit einem zweiten, um sie zurückzunehmen. Was das Team wollte, war schnell gesagt: beide Versionen ausliefern, die nächsten 500 Besucher entscheiden lassen, weitermachen.
DIE HERAUSFORDERUNG
Jedes Deploy war eine Alles-oder-nichts-Wette
Die Plattform hatte keine Experimentier-Infrastruktur. Eine Änderung ging an 100 % der Besucher oder an niemanden, und ein Rollback war ein weiteres Release mit einer weiteren Wartezeit. Es gab keinen Weg, ein Feature 20 % der Besucher zu zeigen und zu vergleichen, also entschieden Meinung und Dienstalter. Eine eigene Experimentierplattform lag außerhalb des Rahmens: kein gehosteter Dienst, keine neue Infrastruktur. Die Antwort musste im bestehenden Django-Stack leben und vom Produktteam bedient werden können, ohne dass ein Entwickler dazwischen sitzt.
DIE LÖSUNG
Prozent-Flags am Besucher, nicht an der Session
Ich habe mich für django-waffle statt für einen gehosteten Dienst wie LaunchDarkly entschieden. Ein gehosteter Dienst wertet Flags bei jedem Request über das Netz aus, braucht ein SDK im Prozess und rechnet pro monatlich aktivem Nutzer ab; waffle wertet im Prozess aus und speichert Flags in derselben PostgreSQL-Datenbank wie alles andere. Der Kern sind Prozent-Flags: Die Visitor-Tracking-Middleware gibt jedem Besucher ohnehin einen deterministischen Hash, und der Prozentwert des Flags ist die Schwelle, mit der dieser Hash verglichen wird. Ein Context Processor stellt den Flag-Zustand jedem Template bereit, und dasselbe Flag wird in Python geprüft, wo sich das Backend anders verhalten muss. Ein eigener FlagAdmin macht den Prozentwert in der Listenansicht editierbar, und so hebt ein Product Manager einen Test mit einem Speichern von 5 % für internes QA auf 10 %, 50 % und 100 %, oder zurück auf 0 %. Der Preis: waffle bringt keine Analytics mit. Das Team nahm den Schalter und machte die Auswertung woanders.
Die Admin-Anpassung, die den Rollout-Prozentwert in die Listenansicht holt:
Python
class FlagAdmin(WaffleFlagAdmin):
list_display = [
'name',
'everyone',
'percent',
'superusers',
'staff',
'authenticated',
'note',
'created',
'modified',
]
list_editable = [
'everyone',
'percent',
'superusers',
'staff',
'authenticated',
'note',
]
list_filter = ['everyone', 'superusers', 'staff']Gleicher Besucher, gleiche Variante
Besucher landen per Hash gegen den Rollout-Prozentwert in A oder B. Drück "Besucher kommt zurück", um einen davon erneut zu schicken, eingeloggt oder nicht: Der Bucket bewegt sich nicht. Dann schalte das Flag ab: Alle sehen A, die Hashes bleiben, und beim Wiedereinschalten ist jede Zuordnung wieder da.
show_new_contact_formanRegelHash < 50 → B
v-0001Hash 58A
v-0002Hash 22B
v-0003Hash 81A
v-0004Hash 0B
v-0005Hash 32B
v-0006Hash 29B
v-0007Hash 2B
v-0008Hash 47B
v-0009Hash 7B
v-000aHash 7B
v-000bHash 62A
v-000cHash 92A
Jeder Besucher wird einmal gehasht. Der Bucket folgt dem Hash, nicht der Session.
12Besucher
4Variante A
8Variante B
67 %Tatsächlicher B-Anteil
0Zurückgekommen, gleiche Variante
Eine Template-Bedingung, keine Python-Änderung:
HTML
{# base template, contact form A/B test #}
{% load waffle_tags %}
{% flag "show_new_contact_form" %}
{# Variant B: simplified form #}
{% include "contact/_form_v2.html" %}
{% else %}
{# Variant A: original form #}
{% include "contact/_form_v1.html" %}
{% endflag %}DAS ERGEBNIS
Kürzere Diskussionen, drei Features nie gebaut
Das Team kam von Meinung zu Messung. Das neue Kontaktformular gewann mit einem klaren Conversion-Plus, eine vereinfachte Preisanzeige senkte die Absprungrate um 11 %, und drei geplante Features wurden vor der Entwicklung gestrichen, weil ein kleiner Rollout kein Interesse zeigte. Eine Idee braucht heute rund zwei Stunden bis zum laufenden Experiment, und eine schlechte Variante ist weg, bevor die meisten Besucher sie gesehen haben. Das Flag-System verursachte in dieser Zeit keinen Vorfall.
WICHTIGE KENNZAHLEN
14A/B-Tests in 18 Monaten
+23%Conversion-Plus, Kontaktformular
30sRollback im Schnitt
KUNDENSTIMME
"Features, über die wir früher wochenlang gestritten haben, gehen jetzt als zwei Versionen live, und die nächsten 500 Besucher entscheiden. Drei Features, von denen wir überzeugt waren, haben niemanden interessiert. Wir haben sie nie gebaut."
Product Manager
B2B-Marktplatz, Produktteam
FÜR DEIN PROJEKT
- Wann es passt
Du betreibst einen Monolithen, Produkt und Engineering sind sich regelmäßig uneinig, was gebaut werden soll, und eine gehostete Experimentierplattform ist für ein Dutzend Tests im Jahr schwer zu rechtfertigen. Flags im Prozess geben dir den Schalter ohne das Abo.
- Was du prüfen solltest
Ob du eine Besucher-Identität hast, die Login und Logout überlebt. Ohne sie bucketen Prozent-Flags Sessions statt Menschen, und die Daten halten nicht. Leg vor dem ersten Test fest, wer ein Flag in Produktion umlegen darf, nicht danach.
- Was es braucht
django-waffle, einen Haken in deine Visitor-Middleware, einen Context Processor und eine kleine Admin-Anpassung: keine neue Infrastruktur. Die Disziplin kostet mehr als der Code. Jedes Flag braucht ein Ticket, ein Enddatum und einen Ausbau, sonst füllt sich die Codebasis mit toten Schaltern.
FAQ
TECHNOLOGIE-STACK
Django
Python
PostgreSQL
Dietmar Eglhofer - Geschäftsführer, Solvster & VIARESDaniel hat bei der Gründung und Umsetzung der Unternehmen Solvster und VIARES einen entscheidenden Beitrag geleistet. Er war verantwortlich für den gesamten technischen Aufbau der Onlinepräsenz, inklusive der Serversetups, der Entwicklung und Optimierung der Website sowie der Sicherstellung der Funktionalität. Besonders beeindruckt hat mich, wie proaktiv und lösungsorientiert er immer an Verbesserungen gearbeitet hat. Daniel war stets sehr responsiv und zuverlässig - es war eine Freude, mit ihm zusammenzuarbeiten. Seine Expertise und sein Engagement haben maßgeblich zum Erfolg beider Projekte beigetragen!
Schließe dich Dietmar an und starte dein nächstes Projekt mit Zuversicht.
Frei für neue ProjekteSchreibe mir