Build in Public

Ich habe Lorem Ipsum in meinem eigenen Testdaten-Generator gefunden

Vor dem Launch habe ich einen gezielten Quality-Pass über die regelbasierte Engine laufen lassen, den Free-Tier-Pfad, der ohne die AI generiert. Hier ist jede Wert-Heuristik, die ich nachgeschärft habe, und warum jede einzelne zählte.

SeedBase · ~5 Min. Lesezeit

SeedBase hat eine Aufgabe: Fake-Daten zu erzeugen, die echt aussehen. Der bezahlte Pfad nutzt dafür ein LLM; der Free-Tier läuft über eine regelbasierte Engine, und genau die wollte ich vor dem Launch wasserdicht haben. Also habe ich das getan, was ich jedem mit seinem eigenen Generator raten würde: ihn mit einem breiten Schema füttern und dann die Ausgabe Spalte für Spalte durchlesen, auf der Jagd nach allem, was ein aufmerksamer User finden würde, bevor er es tut.

Ein solcher Pass ist dafür gemacht, Edge Cases aufzudecken. Das ist der ganze Sinn. Hier ist, was er zutage förderte, in der Reihenfolge, wie sehr mich das jeweils gestört hätte, samt dem Fix für jeden Punkt.

1. Überall Lorem Ipsum

Jedes description-, bio- und notes-Feld war mit lorem ipsum dolor sit amet gefüllt. Slugs lasen sich et-labore-sed-dolor. Für ein Produkt, dessen ganzer Pitch „realistische Daten" ist, ist das die Todsünde.

Warum war es überhaupt da? Niemand hat Lorem Ipsum gewählt. Es ist der Standard-Default. Die regelbasierte Engine griff auf genau die Platzhalterwörter zurück, mit denen jede Faker-Bibliothek ausgeliefert wird, und weil der primäre Pfad das LLM ist, hatte dieser Fallback-Text nie einen richtigen Durchgang bekommen. Defaults bleiben Defaults, bis jemand hinschaut. Genau dafür war dieser Audit da.

Der Fix war zweiteilig. Der offensichtliche: die Platzhalter-Wortliste durch echtes, neutrales englisches Vokabular und einen Pool echter Sätze ersetzen. Der hinterhältige: der Anonymisierungs-Pfad rief die text()-Hilfsfunktion einer Faker-Bibliothek auf, die ebenfalls standardmäßig Lorem Ipsum zurückgibt. Die versteckte sich in aller Öffentlichkeit.

2. Mengen bis 9.000

Eine order_items.quantity von 8.924. Niemand bestellt neuntausend von irgendwas. Die Ursache war ein Reihenfolge-Bug: eine generische „das ist eine Integer-Spalte, nimm eine Zahl bis 9999"-Regel lief vor der Regel, die wusste, dass „quantity" eine kleine Zahl bedeutet. Die Spaltennamen-Heuristiken waren für typisierte Integer-Spalten faktisch toter Code. Nach vorne gezogen, und jetzt ist quantity 1-10, stock begrenzt, Preise realistisch, Ratings 1-5.

3. updated_at vor created_at

created_at: 2026-05-01 23:46
updated_at: 2025-11-27 22:46   <- sechs Monate aktualisiert, bevor es existierte

Jede Zeitstempel-Spalte wurde unabhängig generiert, also hatte etwa ein Drittel der Zeilen ein updated_at, das vor created_at lag, was physikalisch unmöglich ist. Behoben, indem ich den beiden Spalten nicht-überlappende Zeitfenster gab: created_at zieht aus einem älteren Bereich, updated_at aus einem neueren, sodass die Reihenfolge garantiert ist.

4. Namen, die nicht zu ihren E-Mails passten

Ein User namens Mia Koch mit der E-Mail olivia.bauer65@…. Name und E-Mail wurden getrennt gewürfelt. Jetzt leiten sie sich aus derselben Zeile ab, also ist es Alex Miller unter alex.miller@example.com.

5. Bestellsummen, die nicht aufgingen

Das war die subtile, und die, die ein aufmerksamer Mensch wirklich bemerken würde. Die order.total war eine zufällige Zahl ohne Bezug zu ihren Positionen, und jeder order_item.unit_price hatte keinen Bezug zum Katalogpreis des Produkts. Schaust du auf eine Tabelle, sieht es passabel aus. Rechnest du es über die Tabellen hinweg nach, fällt es auseinander:

order.total           = 470,60
sum(quantity × price) = 1.883,20   <- die sollten gleich sein

Der Fix ist ein Rekonziliations-Pass, der nach der Generierung läuft: erst den Katalogpreis jedes Produkts in die Position kopieren, dann jede Eltern-Summe auf die Summe ihrer Kinder setzen. Jetzt passt unit_price zum Katalog und order.total entspricht der Summe seiner Positionen, jedes Mal.

Warum das die eigentliche Arbeit ist

Nichts davon ist glamourös. Niemand postet „ich hab meine Fake-Daten heute ein bisschen weniger fake gemacht". Aber genau das ist der Unterschied zwischen einer Demo, bei der jemand denkt „das ist offensichtlich generiert", und einer, bei der er denkt „Moment, ist das echt?", und diese zweite Reaktion ist das ganze Produkt.

Dahinter steckt eine tiefere Lektion über synthetische Daten allgemein: valide auszusehen ist nicht dasselbe wie kohärent zu sein. Valide heißt, die Typen stimmen und die Constraints gehen durch. Kohärent heißt, ein Name passt zu seiner E-Mail, eine Summe zu ihren Positionen, ein Zeitstempel respektiert die Kausalität. Die meisten „Fake-Daten"-Tools hören bei valide auf. In der Kohärenz lebt der Realismus.

Noch auf der Liste. Kohärente Geografie (eine Stadt, ihre Postleitzahl und ihr Land, die tatsächlich zusammenpassen) kommt als Nächstes, dazu breitere Domänen-Vokabulare. Ehrlich ist besser als perfekt. Das ist aufgeschrieben, nicht übertüncht.

Wenn du die technische Version willst, wie die Beziehungen überhaupt erst konsistent gehalten werden, das habe ich separat aufgeschrieben: fremdschlüssel-konsistente Testdaten aus deinem Schema generieren →

Sieh dir die Daten selbst an

Generiere in etwa fünfzehn Sekunden eine vollständige, kohärente Beispiel-Datenbank, dann richte sie auf dein eigenes Schema. Free-Tier, keine Kreditkarte.

  • Kein Lorem Ipsum
  • Kohärente Werte
  • FK-konsistent
  • EU-gehostet
Kostenlos ausprobieren