Friday, October 30, 2026

One data channel, many calls: the grpc-dc frame protocol

gRPC normally rides on HTTP/2: one TCP connection, many streams, HPACK headers, flow-control windows. WebRTC DataChannels already give us a reliable, ordered, encrypted message pipe — so grpc-over-datachannels replaces the HTTP/2 layer with a small frame protocol designed for that pipe. This post is a tour of the wire format, specified in SPEC.md in the repository.

One message, one frame

DataChannels preserve message boundaries, so every binary message is exactly one frame: a type byte, a 32-bit big-endian stream id, and a payload. The frame types are deliberately few. HEADERS opens a call and carries a small JSON document — the method path and metadata — instead of an HTTP header block. DATA carries exactly one serialized protobuf message, untouched. HALF_CLOSE says the client will send no more, mirroring gRPC semantics. TRAILERS ends the call with status, and RST aborts from either side.

Stream lifecycle

The initiating peer allocates odd stream ids (1, 3, 5, …), the other side even ones, so both peers can open calls without coordination. A full-duplex call is: HEADERS from the client, HEADERS back with initial metadata, any number of DATA frames, HALF_CLOSE, more DATA, then TRAILERS. A unary call is just the degenerate case of one DATA frame each way — there is no separate unary fast path to keep in sync across sixteen runtimes.

The details that matter

Deadlines travel as the familiar grpc-timeout metadata key, recomputed at each forwarding hop. Unknown frame types are ignored, which gives the protocol forward compatibility without a version negotiation. Malformed frames, unknown stream ids, and calls to unregistered methods fail closed with an error status. And because a data channel is a stream of messages rather than bytes, backpressure is handled per stream at the frame level rather than by parsing a byte stream.

The full specification, including tracing propagation and the deliberate divergences from gRPC-over-HTTP/2, lives in the grpc-over-datachannels repository. Try the frames live in the in-browser generator.

No comments:

Post a Comment