Envelope codecs
AnyProtocol keeps application payload serialization separate from transport envelope encoding:
application message -> IMessageSerializer -> TransportEnvelope -> IEnvelopeCodec -> transport frame
IMessageSerializer chooses how an application message is represented in TransportEnvelope.Body. The envelope codec only owns headers and the opaque body bytes. For example, a JSON serializer can be used with a MessagePack envelope codec, and a MessagePack serializer can be used with the binary envelope codec.
Codec choices
| Codec | Use when |
|---|---|
BinaryEnvelopeCodec |
The default, backwards-compatible AnyProtocol wire format is the right choice. |
MessagePackEnvelopeCodec |
A compact internal envelope is preferred and both endpoints are controlled by the same deployment. |
ProtobufEnvelopeCodec |
The envelope is a long-lived or cross-language wire contract. The body remains opaque application data. |
CompressedEnvelopeCodec |
Frames contain large or repetitive data. It decorates another codec and applies compression after envelope encoding. |
All codecs validate the envelope version and common size limits. Header keys are case-insensitive, header values are strings, and malformed or trailing input is rejected. Compression also bounds decompression size and ratio.
Limits and compression defaults
Unless an options object supplies different values, EnvelopeCodecLimits.Default is:
| Limit | Default |
|---|---|
MaxFrameSize |
64 MiB |
MaxBodySize |
64 MiB |
MaxHeaderCount |
1,024 |
MaxHeaderBytes |
1 MiB |
MaxDecompressedSize |
64 MiB |
All size limits are byte counts. MessagePackEnvelopeCodecOptions and
ProtobufEnvelopeCodecOptions use these limits by default. CompressedEnvelopeCodecOptions
defaults to GZip, compresses encoded frames at or above a 256-byte threshold, caps the
compression ratio at 100, and rejects double compression unless AllowDoubleCompression is
explicitly enabled. Brotli is also supported. The decompressed output remains subject to
MaxDecompressedSize.
Selecting a codec per transport
Codec selection belongs to the transport boundary. It is not a global serializer setting. gRPC and ZeroMQ keep their existing constructors, which default to BinaryEnvelopeCodec, and also accept an IEnvelopeCodec:
var codec = new CompressedEnvelopeCodec(new BinaryEnvelopeCodec());
var grpc = new GrpcMessagingProtocol(
channel,
codec,
disposeChannel: true);
var zeroMq = new ZeroMqMessagingProtocol(
new ZeroMqProtocolOptions
{
Role = ZeroMqRole.Client,
RouterEndpoint = "tcp://orders.example:5555",
PublisherEndpoint = "tcp://orders.example:5556"
},
codec);
The sender and receiver at a transport boundary must use compatible codecs. A different codec configuration is rejected as invalid transport data; it must not be treated as a different application message type.
The ASP.NET Core gRPC service accepts an IEnvelopeCodec through dependency injection. Register the same codec configuration for the server and client transport:
builder.Services.AddSingleton<IEnvelopeCodec>(codec);
builder.Services.AddAnyProtocolGrpc();
REST, Kafka, RabbitMQ, and InMemory keep their existing transport-specific envelope mapping and do not require an envelope codec unless a future transport explicitly introduces raw envelope frames.
Wire contracts
The binary codec uses little-endian integers and preserves the existing version-1 layout: magic marker, version, header count, UTF-8 header key/value pairs, body length, and body bytes.
The MessagePack codec uses an explicit envelope DTO with numeric keys for version, headers, and opaque body bytes. The Protobuf codec uses the checked-in EnvelopeFrame schema under src/AnyProtocol.Encoder.Protobuf/Protos/envelope.proto. Compression has its own small wrapper containing a magic marker, wrapper version, algorithm, original length, and bounded payload.