JSON hat Ihre Microservices möglich gemacht. Es würgt zugleich leise Ihren KI‑Stack. Wenn Embeddings, Tool‑Aufrufe und Agent‑Logs weiterhin als hübscher Text über die Leitung gehen, zahlen Sie bei jedem Call einen 2–4x‑Aufschlag auf Bandbreite und CPU. Das sind Geld, Latenz und SLO‑Budget, das Sie nicht zurückbekommen.
Das jüngste „Protobuf for Python, without compromises“-Release auf Hacker News war der nötige Anstoß. Das protobuf‑py‑Projekt hat viele Python‑Fußangeln und Performance‑Klippen beseitigt. Übersetzung: Die letzte gute Ausrede, intern in Ihrer KI‑Datenebene weiter JSON zu verschicken, ist gestorben.
So sieht die JSON‑Steuer 2026 aus
Embeddings
Nehmen wir eine typische 1.536‑dimensionale float32‑Einbettung (6.144 Byte roh). Wenn Sie diese als JSON‑Array von Zahlen serialisieren, kostet jeder Wert oft 8–12 ASCII‑Bytes plus Interpunktion. Mit konservativen 9 Bytes pro Wert sind das ~13,8 KB pro Vektor. Wenn Sie stattdessen die rohen Floats base64‑kodieren (ein gängiger Hack), bläht Base64 exakt um 33 % auf: Aus 6,0 KB werden ~8,2 KB.
Der gleiche Vektor ist also:
- 6,1 KB als Binärdaten (float32)
- 8,2 KB als Base64 (Binary‑in‑Text)
- ~13,8 KB als JSON‑Zahlen
Nennen wir es eine 2,3x‑Strafe JSON vs. Binär. Multipliziert über 10 Millionen Embeddings pro Tag (nicht verrückt, wenn Sie RAG bei 100 QPS betreiben): Sie bewegen ~77 GB unnötige Bytes jeden Tag. Bei $0,05–$0,09/GB Egress sind das $3,8–$6,9K/Monat, die in Luft verbrannt werden – noch vor CPU‑Kosten.
Tool‑Aufrufe und Agent‑Traces
Agent‑Frameworks stopfen gern alles in JSON: Tool‑Inputs, Outputs, Zwischenartefakte. Das ist entwicklerfreundlich, nicht maschinenfreundlich. Geben Sie Pythons Parser einen 150‑KB‑JSON‑Blob, zahlen Sie Dutzende bis Hunderte Mikrosekunden CPU pro Hop. Protobuf/FlatBuffers‑Decoder sind in realen Anwendungen typischerweise 3–5x schneller als Pythons JSON‑Parsing – und sie allokieren keine Strings für jede komma‑separierte Zahl.
Logs und Metriken
Sogar Logs werden unschön. Teams streamen Token‑Logs und semantische Events als JSON über SSE oder WebSocket. Super für den Browser. Zwischen Services dagegen schlecht. Häufig sind 5–10x mehr Bytes „on the wire“ als der eigentliche Informationsgehalt – und alles muss geparst werden, bevor es nützt.
Entscheidungsrahmen: Welches Format für welchen Pfad
Es gibt keinen Allzweckhammer. Nutzen Sie pro Spur Ihrer KI‑Datenebene das passende Wire‑Format. Der Test: Können Sie die Payload mit Luft nach oben auf Ihrem Median‑Knoten in unter 100 Mikrosekunden pro 100 KB bewegen, decodieren und indizieren? Wenn nicht, ändern Sie das Format.
Spur 1: Tool‑Aufrufe und Agent‑Aktionen (RPC)
- Pick: gRPC mit Protobuf.
- Why: Vertraglich definiert, versionierbar, HTTP/2‑Multiplexing, Streaming, bewährt in polyglotten Stacks. Mit den modernen Python‑Bindings (protobuf‑py) vermeiden Sie die Reflection/GC‑Schlaglöcher, die historisch wehgetan haben.
- Notes: Verwenden Sie oneof für variantente Tool‑Outputs, reservieren Sie Feldnummern für Evolution und bleiben Sie, wo möglich, bei primitiven numerischen Typen. Halten Sie Blobs out‑of‑band (Object Store) und übergeben Sie stattdessen inhaltsadressierbare Referenzen.
Spur 2: Embeddings und Batch‑Feature‑Vektoren (Bulk)
- Pick: Apache Arrow für In‑Memory/IPC und Arrow Flight für Netzwerktransport; Parquet für Storage.
- Why: Spaltenorientiert, Zero‑Copy, SIMD‑freundlich. Arrow packt eine 1.536‑dimensionale Float‑Spalte eng in den Speicher und verschickt sie, ohne Floats in Text zu verwandeln. Flight liefert Backpressure‑aware Streaming über gRPC, ohne Batch‑Semantik neu zu erfinden.
- Notes: Halten Sie Batch‑Größen im Bereich 64 KB–4 MB für Durchsatz ohne Head‑of‑Line‑Blocking. Bevorzugen Sie float16/bfloat16, wo akzeptabel; dokumentieren Sie Präzisions‑Trade‑offs.
Spur 3: Realtime‑Streaming zu Browsern (Edge)
- Pick: Behalten Sie JSON oder JSON Lines für Server‑Sent Events zu Browsern bei. Komprimieren Sie mit gzip oder zstd und deckeln Sie die Event‑Größe.
- Why: Browser mögen Text. Kämpfen Sie am Edge nicht gegen die Plattform. Erzwingen Sie aber, dass alle Server‑zu‑Server‑Streams binär sind.
- Notes: Wenn Sie unbedingt Binärdaten in den Browser streamen müssen, nutzen Sie WebTransport oder WebSocket mit ArrayBuffer. Erwarten Sie breitere Kompatibilitätsfragen als bei SSE.
Spur 4: Interne Caches und Queues
- Pick: Verwenden Sie Binärwerte in Redis/Valkey. Für Kafka/Pulsar: Protobuf oder Avro mit Schema‑Registry.
- Why: JSON‑Werte in heißen Caches blähen Speicher und CPU auf. Schema‑bewusste Topics vermeiden Consumer‑Drift und erlauben Feld‑Evolution ohne manuelles Reprocessing.
Harte Zahlen (und ein schneller ROI‑Check)
Hier eine Überschlagsrechnung für ein typisches RAG‑System mittlerer Größe:
- Workload: 120 QPS im Schnitt, jede Anfrage schreibt ein 1.536‑dimensionales Float‑Embedding in einen Feature Store und veröffentlicht einen Tool‑Call‑Trace von ~50 KB.
- JSON‑Baseline: Embedding ~13,8 KB + Trace 50 KB = ~63,8 KB/Request. Das sind ~7,6 MB/s oder 657 GB/Tag über die Services.
- Binary‑Refactor: Embedding 6,1 KB + Trace 15 KB (Protobuf, leicht komprimiert) = ~21,1 KB/Request. ~2,5 MB/s oder 218 GB/Tag.
- Ersparnis: ~439 GB/Tag. Bei $0,05–$0,09/GB Egress: $657–$1.183/Monat allein an Egress. CPU‑Einsparungen übertreffen das meist deutlich: Weniger JSON‑Parsing und GC über Ihre Flotte kann 5–20 % CPU in heißen Services freimachen – bei heutigen Instanzpreisen echtes Geld.
Beachten Sie, wie schnell sich das in Multi‑Region‑ oder Fan‑out‑Topologien potenziert.
Schema‑Design: Bauen Sie Ihr JSON‑Spaghetti nicht in Protobuf nach
Sie gewinnen nicht, indem Sie geschweifte Klammern durch Varints ersetzen. Sie gewinnen, indem Sie Form erzwingen.
- Trennen Sie Blobs von Metadaten: Große Binärarrays (Embeddings, Bilder) in dedizierte Felder oder Streams. Metadaten schlank und typisiert halten.
- Verwenden Sie oneof für Varianten: Tool‑Ergebnisse sollten ein algebraischer Typ sein, kein JSON‑Objekt mit ad‑hoc‑Schlüsseln. Beispiel: result ist eines von: search_result, file_write, http_call.
- Nach vorn versionieren, nicht rückwärts: Felder mit neuen Nummern hinzufügen. Niemals eine Feldnummer umwidmen. Feature Flags oder Fähigkeits‑Aushandlung statt Rätselraten nutzen.
- Numerische Präzision bewusst wählen: float16/bfloat16 halbiert die Bandbreite gegenüber float32. Für Cosine Similarity und ANN meist ausreichend. Dokumentieren, wo nicht.
- Grenzwerte definieren: Max. Array‑Längen, max. String‑Längen. Beim Decodieren durchsetzen. Ihre KI‑Datenebene ist Teil Ihres Security‑Perimeters.
Browser‑Realitätscheck: JSON am Edge, Binär innen
„Aber unser TypeScript‑Frontend…“ Klar. Behalten Sie JSON an der Grenze bei. Verwenden Sie gRPC‑Web oder Connect für Browser‑Kompatibilität, wenn Sie stark typisierte APIs wollen; sie können zum Browser JSON „on the wire“ sprechen, während Ihr Server intern Protobuf spricht.
Die Regel: kein JSON hinter der Edge‑Schicht. Frontends sprechen JSON oder JSON Lines zum Edge; alle Inter‑Service‑Links sind binär. Wenn Sie Embeddings an einen Browser geben müssen (selten), senden Sie sie als ArrayBuffer in einem WebSocket oder WebTransport, nicht als Base64‑Strings in JSON.
Tooling‑Reife 2026: Die Ausreden sind weg
- Python: Die neueren protobuf‑py‑Layer sind schneller und weniger magisch. Sie spielen gut mit Type‑Checkern und vermeiden die GC‑Unruhe, die ältere Wrapper verursachten. Apache Arrows Python‑Bindings sind stabil und produktionsreif; Arrow Flight funktioniert mit asyncio.
- TypeScript/Go/Java: First‑Class‑Compiler und gRPC‑Bibliotheken. Buf‑basierte Workflows erzwingen API‑Breaking‑Change‑Regeln in der CI.
- FlatBuffers und Cap’n Proto: Wenn Ihr Use Case In‑Place‑Reads und ultra‑niedrige Latenz braucht, ziehen Sie diese in Betracht. Der Trade‑off ist eine steilere Lernkurve und rauere Multi‑Language‑Ergonomie als bei Protobuf. Nutzen Sie sie für Hot Paths, nicht überall.
- Schema‑Registries: Confluent‑artige Registries sind nicht nur für Avro. Pflegen Sie ein Repo mit .proto‑Dateien inklusive Lint‑Regeln und generierter Doku; behandeln Sie es als Source of Truth.
Migrationsplan: 30, 60, 90 Tage
Tag 0–30: Messen und eingrenzen
- Payloads instrumentieren: Loggen Sie Wire‑Größen und Parse‑Zeiten pro Route, pro Service. Notfalls 1–5 % des Traffics samplen. Mit Content‑Type taggen.
- Zwei Versuchskaninchen wählen: Ein RPC (ein stark frequentierter Tool‑Call‑Endpoint). Ein Bulk‑Job (Embedding‑Ingest).
- Formate festlegen: gRPC+Protobuf für das RPC; Arrow Flight für den Bulk‑Job. Feldbenennung und Versionierungs‑Policy schriftlich vereinbaren.
Tag 31–60: Dual‑Stack aufbauen
- Typen generieren: .proto‑Dateien in ein Shared‑Repo legen. Sprach‑Bindings als Teil der CI generieren (ts‑proto für TS, protobuf‑py oder protoc‑gen‑mypy für Python).
- Adapter implementieren: Für die gewählten Endpunkte parallel JSON und Protobuf produzieren und konsumieren. Gesteuert per Header oder versioniertem Pfad.
- Wire‑Kompatibilitätstests: Goldene Binär‑Fixtures und Roundtrip‑Tests über Sprachen hinweg erstellen. Einen Fuzz‑Pass für Decoder mit Größen‑Caps hinzufügen, um Parser‑Bomben zu fangen.
- Operative Hooks: Metriken emittieren: decode_failures, decode_latency_p99, payload_ratio (json_bytes/binary_bytes) und Bandbreite pro Route.
Tag 61–90: Umschalten, dann ausrollen
- Edge‑Policy: Erzwingen Sie „JSON nur am Edge“. JSON auf internen Links mit Envoy oder Service‑Mesh‑Policy blocken (Content‑Type Allowlist).
- Base64 abschaffen: Für alle verbleibenden Binär‑Payloads in Text‑Transporten Base64‑Blobs durch Object‑Store‑Referenzen oder Binär‑Streams ersetzen.
- Rollout‑Plan: Einen Hot Path pro Woche migrieren. Erwarten Sie 20–40 % Bandbreitenreduktion pro Service‑Hop und sichtbar mehr CPU‑Headroom.
- Kostencheck: Nach 30 Tagen Egress und CPU vorher/nachher vergleichen. Freigewordene CPU in Latenz‑SLOs oder Instanz‑Downsizing reinvestieren.
Betriebliche Leitplanken
- Observability: Parse‑Fehler müssen First‑Class‑Incidents sein. Auf jeden Spike alarmieren. Pro Format Histogramme von Decode‑Zeiten und Größen führen.
- Backpressure: HTTP/2‑Stream‑Limits und Flow Control in gRPC nutzen. Für Arrow Flight die Anzahl inflight Batches pro Peer begrenzen.
- Security: Behandeln Sie Ihre Deserialisierer wie Ihre SQL‑Clients: fuzzing, caps und wenn möglich nicht im Request‑Thread‑Pool ausführen.
- Datenaufbewahrung: Binäre Payloads kurzlebig halten. Nur Business‑Fakten persistieren. Für Analytics in Parquet mit explizitem Schema und TTL konvertieren.
Abwägungen, denen Sie ins Auge sehen sollten
- Debugbarkeit: Sie verlieren die „einfach curlen“-Leichtigkeit. Kontern Sie mit CLI‑Tools zum Pretty‑Printen von Protobuf und Arrow und machen Sie sie Teil Ihrer Developer‑Images.
- Reibung im Browser: gRPC‑Web und Connect räumen viel auf, aber Sie werden am äußeren Rand dennoch JSON pflegen. Das ist okay – belassen Sie es dort.
- Lernkurve im Team: Ihre Engineers müssen Schema‑Evolution und Disziplin bei Feldnummern lernen. Es lohnt sich; mit Lintern und CI‑Diffs durchsetzen.
- Third‑Party‑APIs: Manche Vector‑DB‑Anbieter setzen weiterhin standardmäßig auf JSON‑Arrays. Wo möglich, nutzen Sie deren binäre/Batch‑APIs. Andernfalls konvertieren Sie am Rand Ihres Systems, nicht in heißen Internals.
Randfälle: Wann JSON ausreicht
- Kleine, selten aufgerufene Endpunkte: JSON ist völlig in Ordnung für einen Settings‑Read oder ein einmaliges Admin‑Tool.
- Öffentliche APIs mit breitem Client‑Ökosystem: JSON für Reichweite beibehalten und Payloads explizit deckeln. Eine binäre Variante Partnern anbieten.
- Human‑in‑the‑Loop‑Logs: Wenn eine Payload ausschließlich von Menschen im Browser gelesen wird, Lesbarkeit priorisieren und aggressiv komprimieren.
Eine einfache Regel zum Institutionalisieren
Binär innen; JSON außen. Hängen Sie es als Poster auf. Machen Sie eine CI‑Regel, die neue JSON‑Felder auf internen Endpunkten blockiert. Fügen Sie eine Dashboard‑Kachel hinzu, die zeigt, wie Ihr JSON‑zu‑Binär‑Trafficanteil Woche für Woche sinkt. Und feiern Sie das erste Mal, wenn Sie 20 % einer Service‑Flotte abschalten, ohne ein SLO zu verletzen.
Die Ältesten des Internets haben uns zu einer Welt interoperablen Textes geführt. Das nächste Jahrzehnt der KI dreht sich um Durchsatz, Latenz und Unit Economics. Das bedeutet veränderbare Verträge und Bytes, die ihr Gewicht tragen. Sie müssen die Welt nicht neu schreiben – hören Sie einfach auf, eine Steuer zu zahlen, die Sie nicht brauchen.
Wichtigste Erkenntnisse
- JSON bläht Embeddings und Traces um den Faktor 2–4 gegenüber Binär auf, und Base64 fügt strikt 33 % Overhead hinzu. Das kostet real Geld und Latenz.
- gRPC+Protobuf für Tool‑Calls, Arrow/Flight für Embeddings und Batch‑Features, und Binärwerte in Caches/Queues einsetzen.
- JSON am Browser‑Edge beibehalten; innerhalb des Meshes Binär erzwingen. Spur für Spur mit Dual‑Stack‑Endpunkten migrieren.
- Payload‑Größe und Decode‑Latenz instrumentieren; Ziel: unter 100 Mikrosekunden pro 100 KB auf dem Median‑Knoten.
- Erwarten Sie 20–40 % Bandbreitenersparnis pro Hop und 5–20 % CPU‑Headroom auf heißen Services nach der Migration.
- Das Ökosystem ist 2026 reif: modernes protobuf‑py, ausgereiftes Arrow und starke TS/Go/Java‑Tooling nehmen frühere Ausreden weg.