Orbitra-Lasttest: 480 Req/s, null Fehler, p99 182 ms
Ein Tracker lebt unter Last: jeder Klick ist ein Schreibvorgang, eine Eindeutigkeitsprüfung und ein Redirect. Deshalb haben wir vor dem v1.6.3-Tag die Eindeutigkeits-Pipeline auf einer Datenbank in Produktionsgröße neu gebaut und auf unserem Teststand mit gestufter k6-Last bombardiert. Hier sind die Zahlen.
Warum wir den Test gefahren haben
v1.6.3 machte den Duplikatfilter ehrlich gegenüber mobilem NAT: Der Eindeutigkeitsschlüssel wurde IP + User Agent statt nur IP. Hinter dem NAT eines Mobilfunkanbieters kollidierten vorher zwei verschiedene Personen — der zweite Besucher bekam eine Subid ohne Klickzeile in der Datenbank, und seine Konversion hatte nichts zum Anbinden.
Die Änderung erforderte eine neue ua_hash-Spalte und einen zusammengesetzten Index auf einer Datenbank, die bereits echtes Volumen trug. Das ist die heikelste Art von Migration — also spielten wir vor dem Tag exakt den Pfad durch, den eine Nutzerinstallation durchläuft — mit Daten in Produktionsgröße.
Der Teststand
- Cloud-Container: 2 vCPU / 7 GB RAM, Ubuntu 24.04. nginx 1.24 + PHP-FPM 8.3 in der Werkskonfiguration, wie
install.shsie hinterlässt — keine Handoptimierung in den Basisläufen. - SQLite im WAL-Modus. k6 läuft auf derselben Maschine (~0,3 Kern Overhead), die Zahlen sind also eher unterschätzt.
- Gestufte Last mit konstanter Ankunftsrate: 60 s pro Stufe, Timeout 5 s, Redirects werden nicht verfolgt.
- Kampagne: ein regulärer Stream → Offer-Redirect, Eindeutigkeitsfenster 24 h über IP + User-Agent. Uniques nutzen eine zufällige öffentliche IP und einen eindeutigen UA; Wiederkehrende 50 feste IP/UA-Paare.
- Drei Datenbanken: ~50 Tsd. Klicks (Sanity), 3,2 Mio. (Haupttest) und ein Snapshot vor dem Upgrade mit 3,9 Mio. für die Migrationsgeneralprobe (~1 Mio. davon in den letzten 24 Stunden, ~8 500 Klicks pro NAT-IP).
- Läufe im Paar: v1.6.2 bediente dieselbe Datenbank neben dem neuen Build; nach einem eingestürzten Lauf wurde gewartet, bis sich der FPM-Rückstau auflöste.
Ergebnisse
| Lauf (3,2-Mio.-DB sofern nicht genannt) | Req/s | Fehler | p99 | CPU |
|---|---|---|---|---|
| Uniques, Werks-FPM (DB ~50 Tsd.) | 480 | 0 | 46 ms | 76% |
| Uniques | 480 | 0 | 75 ms | 77% |
| Wiederkehrende Besucher (50 NAT-Paare) | 480 | 0, ~1% via Spool | 14 ms | 61% |
| Uniques + offenes Panel, Berichte alle 2 s | 320 | 0 | 587 ms | 81% |
| Uniques, getuntes FPM/nginx, Geo aktiv | 560 | 0 | 187 ms | 94% |
| Uniques, absichtlich überlastet | 800 | 27% Timeouts | — | 97% |
Und die Migrationsgeneralprobe auf dem 3,9-Mio.-Snapshot: Der erste Request nach dem „Upgrade“ erledigte Migration 55 in 0,04 s, ein Cron-Lauf baute den Index in 4,8 s und trug 1 008 085 UA-Hashes in 29,6 s nach — und der NAT-Traffic mit 480 Req/s lief mit null Fehlern und p99 182 ms durch, alle Subids in der DB. Die Vorgängerversion verlor im selben Szenario 27 775 Subids; die neue null.
Zwei Details am Rande. Sogar bei 800 Req/s — jenseits des Bruchpunkts — wurde jeder ausgelieferte Redirect trotzdem in die Datenbank geschrieben: Überlastung verschlechtert die Latenz, nicht die Haltbarkeit. Und die Hash-Korrektheit bekam eine eigene Prüfung: Eine Stichprobe von 2 000 Zeilen gegen PHP-crc32 verglichen — null Abweichungen.
Die Ökonomie: Ein Klick kostet rund 2,5 ms CPU, das setzt die Obergrenze einer 2-vCPU-Maschine bei ~550–600 Req/s, CPU-limitiert. Auf 4 vCPU extrapoliert dieselbe Rechnung zu ~1 000 Req/s — bisher nur auf dem Papier, und auch so gekennzeichnet.
Was der Stresstest vor dem Release aufgedeckt hat
Die Hälfte des Werts des Laufs sind die Bugs, die er ausgespült hat. Alle vor dem Tag geschlossen:
- Nicht geschlossene Cursor auf dem Klickpfad verursachten sofortiges SQLITE_BUSY_SNAPSHOT — Klicks wiederkehrender Besucher landeten im Spool statt in der DB.
- Das Debounce keyte nur über die IP — NAT-Nachbarn verloren Klicks und bekamen eine Subid, die nicht existierte.
- Berichts-Datumsfilter nutzten date(created_at, tz) und verfehlten den Index — Berichte krochen auf großen Datenbanken.
- Ein Pixel-INSERT hatte 23 Spalten und 22 Werte — Pixel-Klicks wurden stumm verworfen.
- Alte Zeilen mit NULL-Hash hielten den NAT-Kollaps ein Eindeutigkeitsfenster lang nach dem Upgrade am Leben.
Warum das hält
- SQLite im WAL-Modus, eine Datei, null Extra-Services. Kein ClickHouse, Redis oder MySQL, das RAM frisst — der Flaschenhals ist Disk-I/O, und der skaliert mit Ihrem VPS.
- Eine Schreib-Warteschlange (Spool): Ist SQLite kurz gesperrt, landet der Klick in einer Datei-Warteschlange, die ein Minutencron abarbeitet — der Redirect des Besuchers wartet nicht, und der Klick geht nie verloren.
- Eindeutigkeitsprüfungen per Index: Jeder Klick trägt einen kompakten crc32-UA-Hash, und die vier Prüfungen pro Klick suchen im Index (ip, ua_hash, created_at), statt alle Klicks einer IP zu durchlaufen.
Ehrliche Einschränkungen
- Getestet auf dem Release Candidate von v1.6.3. Die Speicherarchitektur (SQLite, Spool, Indizes) hat sich in aktuellen Versionen nicht geändert.
- Unser Stand ist nicht Ihr VPS: Absolute Zahlen reisen mit der Hardware. Übertragbar sind die Verhältnisse und das Ausfallverhalten.
- Die 4-vCPU-Zahl ist eine Extrapolation, keine Messung — wir sagen es, statt aufzurunden.
- Das war ein synthetischer Stresslauf plus eine Migrationsgeneralprobe in Produktionsgröße — kein A/B gegen andere Tracker auf echtem Traffic.
Was das für Sie bedeutet
Ein bescheidener VPS — die Klasse, die die meisten Guides für den Start empfehlen — hat bereits Reserven für ernsthafte Tagesvolumina, und oben wartet keine Event-Abrechnung. Wenn Sie bei Keitaro bleiben, weil „SQLite überlebt das nicht“ — hier sind die Daten, die Sie ansehen sollten.
Orbitra installiert sich auf einem sauberen Ubuntu-Server in etwa 15 Minuten — ein Befehl; die Live-Demo ist offen, wenn Sie erst einmal am Panel spielen möchten.
FAQ
Auf welcher Hardware lief der Test?
Auf einem Cloud-Container mit 2 vCPU und 7 GB RAM unter Ubuntu 24.04, nginx und PHP-FPM in der Werkskonfiguration von install.sh, k6 auf derselben Maschine — die Zahlen sind also eher unterschätzt. Absolute Werte hängen immer von Ihrem VPS ab: Sie skalieren den Server, nicht den Tarif.
Gelten die Ergebnisse für die aktuelle Version?
Der Test lief auf dem Release Candidate v1.6.3. Die Speicherarchitektur (SQLite + Schreib-Warteschlange + Eindeutigkeitsindizes) ist in aktuellen Versionen identisch; die Änderungen danach sind Features und UI.
Warum SQLite statt ClickHouse?
Eine Datei, WAL-Modus, kein separater Datenbankserver. Bei kleinen bis mittleren Volumina ist der Flaschenhals Disk-I/O, nicht RAM — ein günstiger VPS reicht weit. Für dauerhaft Millionen Klicks pro Tag ist eine kolonnenbasierte Architektur stärker — das sagen wir offen.
Hat die Migration Daten verloren?
Im Szenario wiederkehrender Besucher verlor die Vorgängerversion 27 775 Subids; die neue null. Berichte über 3,2 Mio. Klicks stimmten zeilengenau mit der Vorgängerversion überein.
Weiterlesen
Voluum Alternative: Kostenloser Self-Hosted Tracker
Voluum startet bei ~$149/Monat. Orbitra ist ein kostenloser Self-Hosted-Tracker mit integriertem Cloaking und 50+ CPA-Integrationen. Vergleich und Migrations-Guide.
Artikel lesen →Keitaro Alternative: Kostenloser Self-Hosted Tracker
Der nächste Self-Hosted-Konkurrent — aber die Lizenz startet bei 79 $/Monat. Funktionsvergleich plus 1-Klick-Kampagnenimport.
Artikel lesen →