Files
6f0dfd20c5 docs: complete tooling story (pb2zap + zap2pb), zip server, ZAP-only production case (#1)
* docs: tools section (pb2zap, zap2pb), zip server page, ZAP-only production story

- content/docs/tools/: new Tooling nav group — the complete pb<->ZAP
  interop boundary. pb2zap (go/ast codemod off protobuf), zap2pb
  (the one sanctioned protobuf import: Marshal/Unmarshal/Equal/
  AppendMessage, v0.2.0), and the migration path over the existing
  schema/codegen pages.
- content/docs/zip.mdx: the ZAP-native application server — one
  Listen verb (ZAP primary, HTTP secondary), typed handlers with
  REST/OpenAPI/MCP projections, Mount composition, and the
  hanzoai/cloud case: sub-1,000-line compose root hosting ~75K LOC
  of subsystems (76:1).
- why-zap: scrub the unmeasured benchmark tables (per the
  benchmarks-page policy), replace with mechanism arguments and the
  ZAP-only-in-production account: zero gRPC, protobuf confined to
  the four-function zap2pb boundary at the OTLP edge.
- ecosystem: add zip/pb2zap/zap2pb rows; quick-start + index: link
  the new pages, drop the unmeasured 5-20x claim.

* fix(build): alias MDX collections to regenerated docs/, drop frozen .docs snapshot

next.config.mjs and tsconfig.json pointed @hanzo/docs-mdx:collections/*
at .docs/ — a snapshot frozen on Jun 1 — while the MDX plugin
regenerates docs/ on every build. Result: no page added since the
snapshot (schema, codegen, rpc, capabilities, and this PR%27s tools/zip)
was ever emitted; the site silently served 37 routes instead of 45.
Alias both resolvers at docs/ and remove .docs.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-07 17:58:42 -07:00

130 lines
7.7 KiB
Plaintext

---
title: Why ZAP?
description: What ZAP replaces, what it buys you, and the production stack that runs it with zero gRPC and zero protobuf.
---
# Why ZAP?
ZAP replaces **both halves** of the conventional RPC stack — protobuf (serialization) and gRPC (transport + RPC) — with one layer. This page explains the mechanism, compares the alternatives honestly, and shows what a stack looks like when the replacement is complete: a real production deployment with zero gRPC and protobuf confined to one four-function file.
## The problem
Modern distributed systems inherit four costs from their RPC framework:
1. **Serialization overhead** — JSON and protobuf require an encode/decode step on every hop
2. **Transport lock-in** — most frameworks are welded to a single transport (gRPC to HTTP/2)
3. **Bolted-on trust** — auth is per-layer (TLS *and* tokens *and* API keys), consensus is a separate integration
4. **Two artifacts per contract** — a schema *and* a framework config, each drifting independently
## How ZAP solves these
### Zero-copy serialization
ZAP's wire format is directly usable in memory. There is no parsing step — data is accessed in place from the buffer.
```
Traditional RPC:
Wire -> Parse -> Memory Object -> Use
ZAP:
Wire -> Use (directly)
```
Measured numbers live on the [benchmarks page](/docs/benchmarks) — every table there is reproducible from [zap-proto/bench](https://github.com/zap-proto/bench), and claims that can't be traced to a checked-in harness don't get published. The mechanism argument stands on its own: object-mode access has no decode step to pay for, which is why it leads every mode in the harness.
### Transport flexibility
ZAP abstracts the transport layer:
| Transport | Latency | Reliability | Use Case |
|-----------|---------|-------------|----------|
| TCP | Low | Guaranteed | Default choice |
| UDP | Lowest | Best-effort | Real-time telemetry |
| Unix Socket | Lowest | Guaranteed | Same-host IPC |
| WebSocket | Medium | Guaranteed | Browser clients |
Switching transports requires no code changes:
```go
// TCP (default)
client, _ := zap.Dial("tcp://localhost:9000")
// Unix socket
client, _ := zap.Dial("unix:///var/run/zap.sock")
// WebSocket
client, _ := zap.Dial("ws://localhost:9000/rpc")
```
On the server side, [zip](/docs/zip) takes the same idea further: one `Listen` verb, address scheme selects the transport, ZAP primary and HTTP secondary over the same routes.
### One trust model
Authentication is bound to the transport — mutual [post-quantum KEM](/docs/post-quantum) identity, not TLS-plus-tokens — and authority is expressed as [**capabilities**](/docs/capabilities): references the holder can call but cannot forge, transferable to a third peer, revocable without rotating keys. [The capability mailbox example](/docs/examples/capability-mailbox) shows what this makes possible that bearer tokens structurally cannot express. Optional [BFT consensus](/docs/consensus) rides the same wire.
### First-class code generation
One `.zap` schema is the entire contract — structs, RPC surface, stable opcodes:
```bash
zap generate calculator.zap --lang=go --out=./gen
```
Generation emits a zero-copy View/Builder per struct plus a typed client and server per interface — the [Schema Language](/docs/schema) and [Code Generation](/docs/codegen) pages are the references. The [tools section](/docs/tools) covers the migration path off protobuf.
## ZAP instead of gRPC + protobuf
gRPC and protobuf are two products you adopt together and pay for separately. ZAP is one layer:
| Concern | gRPC + protobuf | ZAP |
|---------|-----------------|-----|
| Serialization | protobuf — encode/decode every hop | zero-copy — the in-memory layout *is* the wire layout |
| Transport | HTTP/2 only | TCP, UDP, Unix, WebSocket; [pluggable](/docs/zip#transport-is-a-value-not-a-method) |
| Schema | `.proto` + ordinals + separate service config | one `.zap` file — structs + interface + opcodes |
| Auth | TLS at the edge, tokens in-band | identity-bound transport, PQ KEM, capabilities |
| Browser | requires grpc-web proxy | native WebSocket |
| Streaming | bidirectional | bidirectional + promise pipelining |
| Consensus | separate integration | built-in, optional |
**Choose gRPC when**: you need its ecosystem — existing proto contracts with external partners, off-the-shelf interceptor middleware, teams fluent in it.
**Choose ZAP when**: you control both ends of the wire and want one wire format, one trust model, and no serializer between layers.
## ZAP-only in production
This is not a roadmap claim. The Hanzo AI + Lux Network stack runs ZAP-native today, with **zero gRPC and zero protobuf in application code**:
- **One binary.** [hanzoai/cloud](https://github.com/hanzoai/cloud) composes IAM, KMS, gateway, commerce, AI, and a dozen more subsystems into a single Go binary. The compose root is under 1,000 lines of [zip](/docs/zip) hosting ~75,000 lines of subsystem code — a 76:1 ratio of product over framework shim.
- **One wire contract per service.** Every RPC surface is a `.zap` schema — structs plus stable opcodes. [hanzoai/tasks](https://github.com/hanzoai/tasks) (`schema/tasks.zap`) states it the way every service does: *"This is the one and only wire contract. Nothing on this wire speaks protobuf, gRPC, or any temporal.io-branded framing."*
- **One protobuf touchpoint.** Observability is the industry edge that still speaks protobuf (OTLP/OpAMP). The stack's entire protobuf surface is [zap2pb](/docs/tools/zap2pb) — one file, four functions. Spans are OTLP-protobuf payloads shipped over ZAP frames to the collector's ZAP receiver; no OTLP-over-gRPC, no second protobuf import anywhere.
- **Mechanical migration.** [pb2zap](/docs/tools/pb2zap) rewrote the unambiguous protobuf construction sites; humans restructured the read paths it reported.
The same dispatch generalizes upward: Hanzo and Lux run services as ZAP-native plugin VMs — ZAP is the dispatch surface, Lux consensus orders it, zapdb persists it. Deployments and their numbers are tracked on the [ecosystem page](/docs/ecosystem).
## When to use ZAP
- **High-throughput services**: financial systems, game backends, real-time analytics
- **Low-latency requirements**: trading systems, live collaboration, IoT
- **Distributed consensus**: blockchain nodes, distributed databases, leader election
- **Polyglot environments**: services in Go, Rust, and TypeScript communicating seamlessly
- **Agent infrastructure**: [MCP](/docs/protocols/mcp) and [A2A](/docs/protocols/a2a) ride the ZAP wire natively
## When not to use ZAP
- **Simple public REST APIs**: standard HTTP may be all you need
- **Contracts you don't own**: if external partners mandate proto/gRPC contracts, you keep them — though [zap2pb](/docs/tools/zap2pb) shows how narrow that edge can be
- **Browser-only products**: if browsers are your only client, GraphQL or plain HTTP may fit better
## Performance
Every published number is on the [benchmarks page](/docs/benchmarks), reproducible from the harness in [zap-proto/bench](https://github.com/zap-proto/bench). The honest summary: ZAP wins modestly at small payloads, ties in the middle, and the strongest arguments today are mechanism, not microseconds — one wire format under every protocol, PQ at the transport, capabilities instead of tokens.
## Summary
1. **One layer** replaces protobuf + gRPC — zero-copy wire, typed RPC, transport choice
2. **One trust model** — identity-bound transport, capabilities, optional BFT
3. **One schema** per service — `.zap`, with a [complete toolchain](/docs/tools) on and off it
4. **Proven in production** — a real stack runs ZAP-only, with protobuf confined to four functions
If you control both ends of your wire, ZAP removes an entire layer of your stack. The [quick start](/docs/quick-start) takes five minutes.