Dieser Artikel beantwortet eine spezifische Frage – wie man eine Backend-API auf reproduzierbare Weise bewertet – indem er das Protokoll dokumentiert, das wir bei Aurabase anwenden werden, bevor wir irgendwelche Leistungszahlen veröffentlichen. Keine Ergebnisse: eine Methode. Alle Messungen, die bereits an anderer Stelle auf dieser Website veröffentlicht wurden (insbesondere auf unserer Seite Performance), die nicht bereits auf diesem Protokoll basieren, sollten bis auf Weiteres als ungeprüft betrachtet werden.
Das Wesentliche
Bisher liegen keine Aurabase-Leistungsergebnisse nach einem veröffentlichten, reproduzierbaren Protokoll vor – dieser Artikel dokumentiert die Methodik, die wir anwenden werden, um sie zu erstellen, nicht die bereits erzielten Ergebnisse. Das Repository enthält bereits eine dreistufige -Testsuite: Criterion.rs-Mikrobenchmarks für 3 Kisten, k6-Lasttests für 8 HTTP/WebSocket-Szenarien und ein Python-Skript für den direkten Vergleich von Postgres und API mit Perzentilberechnung. Das vollständige Protokoll – Messdauer, Perzentile statt Durchschnittswerte, Umgebungsisolation, Versions- und Datumsoffenlegung – basiert auf verifizierten externen Quellen: PostgreSQL, Criterion.rs, k6 (Grafana), HdrHistogram, PlanetScale und Convex. Alle Leistungsansprüche, die bereits an anderer Stelle auf dieser Website veröffentlicht wurden, ohne auf dieses Protokoll zurückzuführen zu sein, sollten als ungeprüft betrachtet werden.
Warum wir keine nackten Zahlen veröffentlichen
Convex, Herausgeber eines konkurrierenden responsiven Backends, hat sich öffentlich von dem distanziert, was sein technisches Team als „Balkendiagrammkrieg“ zwischen Datenbankanbietern bezeichnet. Seine Formel ist direkt: „Es geht um Skalierungstheater, nicht um Skalierung“ – Skalierungstheater, nicht um echte Skalierung (stack.convex.dev/on-competitive-benchmarks, technischer Stack-Blog, abgerufen am 23. August 2026).
Sein zentrales Argument: Ein Benchmark, der zwei Systeme mit unterschiedlichen Garantien für Konsistenz, Topologie oder Preismodell vergleicht, testet oft nicht dasselbe, selbst wenn er behauptet, dies zu tun – „der Benchmark testet nicht tatsächlich dasselbe“. Dieser Reflex hat in der Branche einen Namen: benchmarketing, wobei eine Zahl veröffentlicht wird, die aufgrund ihrer Marketingwirkung und nicht aufgrund ihrer methodischen Genauigkeit ausgewählt wurde.
Unsere Antwort besteht nicht darin, die Messung zu verweigern – die Veröffentlichung einer Zahl auf unbestimmte Zeit zu verweigern wäre ebenso unehrlich wie die Veröffentlichung einer unbegründeten Zahl. Es geht darum, zunächst zu dokumentieren, wie wir messen würden, mit welchen Werkzeugen und unter welchen Bedingungen, bevor wir behaupten, etwas gemessen zu haben. Dies unterscheidet auch einen nützlichen Vergleich (wie unseren Aurabase vs. Appwrite-Vergleich, der nachweisbare Architekturunterschiede dokumentiert) von einem Vergleich von Leistungszahlen ohne gemeinsames Protokoll.
Dies ist besonders wichtig für einen technischen Leiter oder einen CTO, der eine Backend-Entscheidung in einem technischen Ausschuss verteidigen muss: Eine Zahl, die nicht auf eine Methode zurückgeführt werden kann, übersteht die erste, etwas eindringliche Frage nicht. Ein dokumentiertes Protokoll dient der Selbstverteidigung – Sie können das Skript und die getestete Version zeigen und den Test bei Bedarf erneut vor jemandem ausführen.
Was die meisten Backend-Benchmarks irreführend macht
Zwei Fallstricke tauchen systematisch auf: der Vergleich verschiedener Topologien ohne Meldung und die Messung der Latenz auf eine Weise, die genau die Pausen verbirgt, die für den Benutzer am wichtigsten sind.
Zum ersten Punkt dokumentiert PlanetScale explizit seine Hardware-Paritätsbeschränkung: Jede verglichene Umgebung muss auf Rechenressourcen (vCPU, RAM) laufen, die gleich oder größer als die Referenzinstanz sind, in derselben Cloud-Region (planetscale.com/benchmarks, „Telescope“-Methodik, abgerufen am 23. August 2026). Ohne diese Disziplin könnte eine Latenzlücke lediglich auf eine größere Maschine zurückzuführen sein – und nicht auf eine schnellere Architektur.
Das gleiche Prinzip gilt für den Cache-Status und die Netzwerktopologie. Eine gerade gestartete Instanz (kalter Postgres-Cache, leerer Verbindungspool, Abfrageplan noch nicht zwischengespeichert) reagiert strukturell langsamer als eine Instanz, die seit einer Stunde unter stabiler Last läuft. Eine Abfrage aus derselben Region wie die Datenbank reagiert strukturell schneller als eine regionsübergreifende Abfrage. Zwei Benchmarks, die keines von beidem angeben, sind einfach nicht vergleichbar, selbst wenn sie identische Einheiten anzeigen.
Im zweiten Punkt heißt die Falle koordinierte Auslassung. HdrHistogram, das von Gil Tene erstellte Referenzprojekt zur Latenzmessung, erklärt es folgendermaßen: Wenn ein Lastgenerator auf die Antwort einer Anfrage wartet, bevor er die nächste sendet (geschlossene Schleife), verringert eine Dienstpause automatisch die Anzahl der während der Pause gesendeten Anfragen – und damit die Anzahl der aufgezeichneten Messungen mit hoher Latenz (github.com/HdrHistogram/HdrHistogram, abgerufen im August 23, 2026). Das Projekt liefert ein konkretes und quantifiziertes Beispiel: Auf einem hypothetischen System, das seine Latenz 200 Sekunden lang alle 10 ms abtastet, reicht eine einzelne Pause von 100 Sekunden in der Mitte des Tests aus, um ohne Korrektur ein Histogramm zu erstellen, in dem etwa 99,99 % der Antworten unter 1 ms zu passen scheinen – obwohl in dieser einzelnen Pause die Hälfte der Echtzeit vergangen ist.
Ein Closed-Loop-Lasttest, der eine Anfrage erst sendet, nachdem die vorherige Antwort empfangen wurde, stellt lange Pausen systematisch unterrepräsentiert. Der angezeigte p99 ist möglicherweise besser als die Realität, die ein echter Benutzer erlebt – nicht weil das System schnell ist, sondern weil das Messprotokoll „vergessen“ hat, die Abfragen im Pausenzustand zu senden.
Warum der Durchschnitt liegt: S. 50, S. 95, S. 99
Eine durchschnittliche Latenz kann ausgezeichnet erscheinen, wenn eine von zwanzig Anfragen fünfmal so lange dauert. Genau das verraten die Perzentile und was der Durchschnitt strukturell verbirgt.
Mechanisch gesehen gibt es an einem Perzentil nichts Geheimnisvolles: Sortieren Sie alle gemessenen Latenzen in aufsteigender Reihenfolge und nehmen Sie dann den Wert an der entsprechenden Position. Von 1000 sortierten Abfragen ist p50 der 500. Wert, p95 der 950. und p99 der 990. Wert. Eine einzige ungewöhnlich langsame Anfrage unter 1000 reicht aus, um den p99 in Bewegung zu setzen – gerade seine Empfindlichkeit gegenüber seltenen Fällen macht ihn nützlich, wo dieselbe isolierte Anfrage im Durchschnitt fast keine Auswirkung hat.
Verräterisches Zeichen: Der Textbericht, den pgbench – das offizielle PostgreSQL-Benchmark-Tool – standardmäßig anzeigt, gibt einen Durchschnitt und eine Standardabweichung an, keine Perzentile (postgresql.org/docs/current/pgbench.html, abgerufen am 23. August 2026). Die offizielle Dokumentation warnt außerdem: „Glauben Sie niemals einem Test, der nur ein paar Sekunden läuft.“ – Glauben Sie niemals einem Test, der nur ein paar Sekunden läuft, was sowohl für die Dauer als auch für die gewählte Metrik gilt.
k6, das Ladetool, das wir für Level 2 unserer Suite verwenden, löst dieses Problem mit in Perzentilen ausgedrückten Schwellenwerten: Die Syntax p(95)<500 definiert ein Pass/Fail-Kriterium – 95 % der Anfragen müssen innerhalb von 500 ms antworten – direkt in der Testkonfiguration (grafana.com/docs/k6, konsultiert am 23. August 2026).
| S. 50 (Median) | Die Hälfte der Abfragen ist schneller als dieser Wert | Versteckt den Verteilerschwanz vollständig |
|---|---|---|
| p95 | 1 von 20 Abfragen ist langsamer | Bereich, in dem die ersten unzufriedenen Benutzer auftauchen |
| p99 | 1 von 100 Abfragen ist langsamer | Am empfindlichsten gegenüber koordinierten Unterlassungen, wenn das Protokoll schlecht gestaltet ist |
Die 3 Benchmark-Level sind bereits in unserem Repository vorhanden
Die Veröffentlichung einer Methodik ohne echte Werkzeuge wäre nur eine weitere Form des Theaters. Der Ordner benchmarks/ im Aurabase-Repository enthält bereits eine dreistufige Suite, die in ihrer Struktur von der öffentlichen Supabase-Methodik inspiriert ist – die Tools existieren, die gemessenen und datierten Ergebnisse existieren noch nicht.
Ebene 1 – Mikro-Benchmarks Criterion.rs
Drei Kisten des Cargo-Arbeitsbereichs verfügen über dedizierte CPU-gebundene Benchmarks: aura-crypto (Argon2-Hash, JWT HS256 – Generierung, Validierung und Signatur für PostgREST, AES-GCM-Verschlüsselung), aura-db-adapters (Analysefilter und select im PostgREST-Format – eq., gte., in.(), Beziehungseinbettungen) und aura-core (JSON-Serialisierung, schema_name-Auflösung, UUID-Validierung).
aura-db-adapters misst speziell die Kosten für das Parsen von Abfragen im PostgREST-Format – vier Fälle für Filter (simple_4, complex_10, or_group, in_large_50 mit 50 Werten) und vier für select (einzelne Spalten, *, eine Beziehungseinbettung, fünf Einbettungen). Dies ist die Art von Kosten, die bei einem globalen Lasttest nicht sichtbar sind: Eine Regression bei der Analyse eines komplexen or.(...)-Filters würde am p95 eines wenig genutzten Endpunkts fast nichts ändern, würde aber an einem Endpunkt mit hohem Datenverkehr messbar werden – daher das Interesse, ihn in einem Mikro-Benchmark zu isolieren, anstatt sich ausschließlich auf Ebene 2 zu verlassen.
aura-core verfolgt einen anderen Ansatz: Anstatt die Rohzeit zu messen, misst es den -Durchsatz (Throughput::Bytes) bei der JSON-Serialisierung und Deserialisierung interner NatsRequest/NatsResponse-Nachrichten, die zwischen dem Gateway und den Diensten ausgetauscht werden – mit drei realistischen Nutzlastgrößen (eine minimale Anfrage, eine Anfrage mit verschachteltem JSON-Körper, eine 50-Zeilen-Listenantwort).
Criterion.rs misst nicht nur die Zeit einer Schleife. Es führt zunächst eine Aufwärmphase durch, um die CPU-/OS-Caches zu füllen, erkennt Ausreißer mit einer modifizierten Version der Tukey-Methode (ohne sie aus dem Datensatz auszuschließen), berechnet Konfidenzintervalle durch Bootstrapping auf einer großen Anzahl neu abgetasteter Stichproben und erkennt Leistungsregressionen zwischen zwei Läufen durch den statistischen Student-Test mit einem konfigurierbaren Rauschschwellenwert – typischerweise ±1 %, um Abweichungen zu ignorieren, die statistisch nicht signifikant sind (bheisler.github.io/criterion.rs/book/analysis.html, abgerufen am 23. August 2026).
Jeder Criterion-Lauf generiert einen detaillierten HTML-Bericht in target/criterion/ – Verteilungen, Regressionsdiagramme, Vergleich mit dem vorherigen Lauf. Es ist diese Beziehung, nicht nur eine Endlinie, die durch eine ernsthafte Methodik wiederhergestellt werden muss.
Stufe 2 – k6-Lasttest
Acht k6-Skripte decken das -Gateway auf der Datenebenenseite ab: health (Latenzbasislinie), auth-flow (Registrieren → Anmelden → Aktualisieren → Abmelden), crud-read und crud-write, storage (Upload/Download), realtime-ws, breakpoint (Lasterhöhung bis Fehler) und supabase-compare. Sieben sind mit einem dedizierten Makefile-Ziel verbunden – supabase-compare.js existiert im Repository, hat aber noch kein Ziel, ein Sachverhalt, den dieser Artikel so dokumentiert, wie er ist, anstatt ihn zu verschleiern.
Die gemeinsame Konfiguration definiert Schwellenwerte pro Vorgangstyp. Hierbei handelt es sich um Pass/Fail-Kriterien, die der Test bei jeder Ausführung überprüft – keine bereits gemessenen Ergebnisse:
| Lesen (GET) | p95 < 500 ms · p99 < 1000 ms | Config k6 (benchmarks/k6/lib/config.js) |
|---|---|---|
| Schreiben (POST/PATCH) | p95 < 300 ms · p99 < 1000 ms | Konfiguration k6 |
| Auth (Anmeldung/Aktualisierung) | p95 < 300 ms · p99 < 1000 ms | Konfiguration k6 |
| Speicherung (Upload/Download) | p95 < 500 ms · p99 < 2000 ms | Konfiguration k6 |
| Fehlerquote, alle Szenarien | < 1 % | Konfiguration k6 |
Der README.md im Ordner benchmarks/ dokumentiert einen Leseschwellenwert von p95 bei < 200ms („Supabase SLO“), während der tatsächlich in benchmarks/k6/lib/config.js – dem, den der Test ausführt – angewendete Schwellenwert p(95)<500ist. Die beiden Dateien sind voneinander abgeleitet. Dies ist ein konkretes Beispiel, das beim Lesen des Quellcodes für diesen Artikel gefunden wurde und zeigt, warum ein Protokoll eine einzige versionierte Quelle der Wahrheit haben sollte, anstatt an zwei Stellen dokumentiert zu sein: Ohne diese Quelle veröffentlicht selbst ein Team, das sich streng anstrengt, am Ende widersprüchliche Schwellenwerte.
Ebene 3 – Direkter Vergleich von PostgreSQL und API
Ein Python-Skript (direct_vs_api.py) misst den tatsächlichen Overhead der Gateway- und Serviceschicht, indem es direkte psycopg2-Anfragen mit HTTP-Aufrufen für denselben Vorgang vergleicht – Liste, einmaliges Lesen nach ID, gefiltertes und sortiertes Lesen. Auf jede Messung folgt eine Aufwärmphase von 10 Iterationen vor der zeitgesteuerten Schleife. Anschließend werden der Durchschnitt, p50, p95, p99 und ein Durchsatz in Vorgängen pro Sekunde berechnet.
Ein zweites Skript (aurabase_vs_supabase.py) wendet dieselbe Aufwärm- und Perzentilberechnungslogik auf einen direkten Vergleich mit einer lokalen Supabase-Instanz (Supabase CLI, standardmäßig localhost:54321) an – dieselbe Maschine, dasselbe lokale Netzwerk für beide, genau die Umgebungsparitätsdisziplin, die PlanetScale für seine eigenen Vergleiche dokumentiert.
Ein Orchestrierungsskript (collect_baseline.sh, Ziel bench-baseline von Makefile) verbindet die drei Ebenen – Criterion auf den 3 Kisten, eine Teilmenge der k6-Szenarien (health und crud-read heute, noch nicht alle 8), dann den Python-Vergleich – und schreibt Protokolle, JSON- und Criterion-HTML-Berichte in einen Ordner mit eindeutigem Zeitstempel: benchmarks/results/AAAAMMJJ_HHMMSS/. Dies ist genau der Reflex der datierten Offenlegung in einem einzigen reproduzierbaren Durchlauf, den der folgende Abschnitt in einem vollständigen Protokoll formalisiert.
Das Protokoll wenden wir an, bevor wir eine Zahl veröffentlichen
Acht Verpflichtungen, die jeweils in einer Praxis verankert sind, die bereits durch ein anerkanntes Tool oder Projekt eines Drittanbieters dokumentiert ist – das nicht für diesen Anlass erfunden wurde.
- Vorwärmen getrennt von der Messung. Criterion.rs füllt CPU/OS-Caches vor dem Timing;
pgbenchempfiehlt ausdrücklich, niemals an einen Lauf zu glauben, der nur wenige Sekunden dauert. - Feste Dauer, keine feste Anzahl von Iterationen. Eine Last braucht Zeit, um zu konvergieren – das ist die Rolle von
stagesk6 und dem Flag-Tvonpgbench. - Perzentile, niemals nur der Durchschnitt – und aktive Wachsamkeit bei koordinierten Unterlassungen, wenn der Lastgenerator in einem geschlossenen Regelkreis arbeitet.
- Umgebung im Detail dokumentiert: Git-Commit des getesteten Dienstes, Version von PostgreSQL, Hardwarespezifikation, Version des Ladetools. PlanetScale dokumentiert seine genauen TPCC-Parameter (
TABLES=20,SCALE=250, ~500 GB) aus genau diesem Grund – ohne diese Details kann niemand einen Lauf reproduzieren. - Mit Zeitstempel versehene und versionierte Ergebnisse, niemals eine einzige Zahl ohne Datum auf einer Marketingseite eingraviert. Die aktuellen Werkzeuge sind bereits in einer veralteten Datei gespeichert; Es wird notwendig sein, diesen Reflex auf jede öffentlich veröffentlichte Messung auszudehnen, wobei die Hosting-Region wie jede andere Umgebungsvariable dokumentiert wird (siehe unseren Leitfaden zu EU-Hosting-Souveränität, relevant, sobald eine Zahl von einer bestimmten Region abhängt).
- Skripte und Rohdaten werden neben dem Gesamtergebnis veröffentlicht, nicht nur als endgültiger Durchschnitt. PlanetScale lädt die Leser sogar dazu ein, einen methodischen Fehler an einer speziellen Adresse zu melden – eine Haltung, die wir für gesund halten und die wir übernehmen möchten.
- Angekündigter Durchsatz neben Latenz, nicht nur das eine oder das andere. Ein System kann bei geringer Last eine hervorragende Latenz aufweisen und mit zunehmender Parallelität im Durchsatz einbrechen – genau das soll das
breakpoint-Szenario (Scale-to-Crash) unserer k6-Suite offenbaren und dieThroughput::Bytes-Mikrobenchmark-Messung von Criterion auf Funktionsebene erfassen. - Erhebliche Lücke vor der Ankündigung einer Verbesserung. Eine Variation von ein paar Prozent zwischen zwei Läufen kann eher ein Messrauschen als ein echter Gewinn sein – Criterion.rs berechnet eine Wahrscheinlichkeit, dass der beobachtete Unterschied auf Zufall zurückzuführen ist, bevor er als Regression oder Verbesserung qualifiziert wird. Eine isolierte Zahl ohne diese Überprüfung ist nur eine statistische Anekdote.
Was wir nicht tun werden
Diese Liste zählt genauso viel wie das Positivprotokoll oben.
- Vergleich verschiedener Topologien (selbst gehostete vs. verwaltete, kalte vs. vorgeheizte Instanz) ohne explizite Meldung.
- Behalten Sie den besten Lauf von zehn bei, ohne die anderen neun zu erwähnen.
- Veröffentlichen Sie eine Figur ohne Datum, ohne Serviceversion, ohne Reproduktionsskript.
- Veröffentlichen Sie eine vorhandene Marketingfigur erneut, solange sie nicht auf dieses Protokoll zurückzuführen ist.
- Wir vergleichen uns mit einem Wettbewerber anhand einer reinen Leistungszahl, wenn dieser Wettbewerber seine eigene Methodik nicht in gleichwertiger Weise veröffentlicht – eine Zahl versus Schweigen ist kein Vergleich, sondern ein Slogan.
Eine Zahl wie „Kaltstart weniger als 1 ms“ wurde verbreitet, ohne dass sie durch einen reproduzierbaren Benchmark untermauert wurde. Es wird jetzt intern als nicht unterstützt behandelt und sollte nicht als gemessene Eigenschaft des Produkts gelesen werden, bis eine datierte Messung mit veröffentlichter Methodik dies bestätigt. Das ist genau die Art von Behauptung, die mit diesem Protokoll verhindert werden soll, dass sie sich wiederholt.
Das minimale Protokoll zum Benchmarking jedes Backends
Dieses Protokoll ist nicht von einem bestimmten Aurabase-Tool abhängig – Sie können es noch heute auf Ihre eigene API anwenden.
- Legen Sie die Last vor des Tools fest: schreibgeschützt, schreibend, realistische Mischung für Ihre Anwendung – kein generisches Verhältnis, das aus einem anderen Projekt kopiert wurde.
- Trennen Sie die Vorheizphase explizit von der Messphase.
- Führen Sie den Test lange genug durch – Minuten, nicht Sekunden.
- Messen Sie in Perzentilen (p50/p95/p99), niemals nur im Durchschnitt.
- Stellen Sie sicher, dass sich Ihr Lastgenerator nicht im geschlossenen Regelkreis befindet, oder korrigieren Sie die fehlende Koordination in der Analyse.
- Isolieren Sie die zu testende Umgebung – keine lauten Nachbarn, keine konkurrierenden Hintergrundaufgaben.
- Veröffentlichen Sie die getestete Version, das getestete Datum, die Hardwarespezifikation und das Skript – nicht nur das Endergebnis.
Auf einer reinen Postgres-Basis benötigt dieses Protokoll einen Befehl pgbench – 20 gleichzeitige Clients, verteilt auf 4 Threads, für 5 Minuten, mit einem Fortschrittsbericht alle 10 Sekunden:
Referenzwerkzeuge, nach Level
Fünf Tools, jedes für eine andere Ebene des Stapels geeignet – keines ersetzt das andere.
| Mikrofon (Funktion) | Kriterium.rs | Reine CPU, Bootstrap-Statistiken |
|---|---|---|
| SQL-Abfrage | pgbench | TPC-B-ähnliche Transaktion, TPS und Latenz |
| HTTP/WS-Last | k6 (Grafana) | Perzentile, Bestanden/Nicht bestanden-Schwellenwerte |
| OLTP im Maßstab | sysbench + TPCC (Teleskop-Methodik) | QPS, Kosten pro Leistung |
| Maßkorrektur | HdrHistogramm | Kompensiert koordiniertes Unterlassen |