ADR 010: Explicit RPC Correlation via cid in the Envelope
- Date: 2025-11-23
- Status: Accepted
- Applies to: RPC
- Tags: rpc, correctness, future-proofing, layering
- Supersedes: Incorrect correlation text in
docs/protocols/rpc/envelope.md
Context
The RPC envelope spec incorrectly referenced a non-existent MessageFrame.ackFrameId field for correlation. The attempted fix—reusing the request's frameId on the response—violates the invariant that frameId is sender-local unique, making multi-hop and observability impossible.
We need explicit correlation that works in single-hop, streaming, fan-out, relay, and offline scenarios.
Decision
frameIdsemantics remain pure: sender-local unique per wire format spec. No reuse by receivers.Add explicit
cid(correlation ID) field to the RPC envelope payload.Envelope schema (inside
MessageFrame.data):tsinterface RpcRequest { t: "r"; m: string; p?: unknown; cid: FrameId; } interface RpcSuccess { t: "R"; cid: FrameId; result?: unknown; } interface RpcError { t: "E"; cid: FrameId; code: number; message: string; data?: unknown; } interface RpcNotification { t: "N"; e: string; d?: unknown; } // no cidCorrelation model: Requests set
cidto their request frame'sframeId. Responses copy thatcidunchanged. Runtime matches oncid, notframeId.No wire format changes. Envelope payload only; backward compatible.
Updated Specification
See updated docs/protocols/rpc/envelope.md for the complete envelope specification with corrected correlation section.
Consequences
- Streaming RPC: Multiple responses per request (same
cid, differentframeIds) - Multi-hop / relays:
cidend-to-end;frameIdhop-local - Observability:
frameIduniqueness invariant preserved - Future evolution: Envelope payload can evolve independently of wire format
Rationale
- Layering: Correlation is explicit in RPC envelope;
frameIdstays pure at wire layer - Industry-standard: Used by NATS, CloudEvents, Kafka, gRPC
- Minimal cost: 16 bytes per RPC request/response
- Minimal surface: No new fields on frames; existing invariants preserved
Alternatives Considered
| Alternative | Why Rejected |
|---|---|
Reuse request frameId on response | Breaks sender-local uniqueness; impossible for multi-hop/relays |
Use AckFrame for RPC responses | Conflates transport ACK with app semantics |
| Embed correlation in subject | Brittle; limited length; creates awkward subject names |
References
docs/protocols/rpc/envelope.md(correlation model)- ADR-006 (RPC envelope – correlation section updated)
- ADR-002 (naming matrix)