If one of these matches what you're building, jump straight to that section. The rest of the post is the vocabulary and the trade-offs behind these picks.
Vocabulary used in the landscape below. Whether a dimension matters more or less is case-by-case — depends entirely on what you're trying to build.
| Dimension | Concepts | Purpose |
|---|---|---|
| Communication Paradigm | pub/sub, request/reply, long-running action (cancelable + feedback), streaming | Fit Which communication shapes does my use case actually need? |
| Topology Model | brokerless, broker-centric, hybrid, client-server | Deploy Am I willing to run a central process? What dies if it goes down? |
| Network Reach | intra-host (SHM/IPC), LAN (multicast/mDNS), WAN (NAT/TLS/edge) | Topology Where do producers and consumers live, and how far apart on the network? |
| Schema & Contract Style | Strict IDL with codegen (.proto, .idl) vs. free-form payload by documentation; protobuf, IDL/CDR, JSON, MessagePack, raw bytes | Contract Is the wire contract enforced by the compiler, or only by docs and discipline? |
| Cross-Language Support | Number of officially supported bindings; API and feature parity across them | Reach Can a polyglot team all speak it natively? |
| Real-Time Behavior | Latency floor, jitter, kernel bypass, lock-free queues, predictability under load | Timing Can it close a control loop or carry uncompressed video? |
| Deployment Complexity | Brokers, IDL/codegen, TLS/certs, service discovery, network setup needed | Ops How many steps from zero to a working hello-world across two machines? |
| Delivery & QoS | at-most/at-least/exactly-once, ordering, deadline, durability, history | Reliability What happens when a message is lost, late, or duplicated? |
| Cross-Platform Support | Linux/Windows/macOS, RTOS, browser/wasm, embedded MCU, mobile | Reach Will every device form-factor in my fleet run it? |
| Footprint / Lightweight | Binary size, runtime memory, dependency depth, optional or mandatory daemon | Cost Does it fit on the smallest target in the system? |
| Discovery | Multicast (SPDP), mDNS, registry / Discovery Server, DNS, static config | Bootstrap How do nodes find each other when they come online? |
| Persistence & Replay | On-disk log, message TTL, history depth, late-joiner catch-up | Recovery Can a new subscriber receive past data, or only what arrives after? |
| Security | TLS/mTLS, ACL/RBAC, payload encryption, signed identity | Compliance Is it safe to run across organizations or the public internet? |
| Ecosystem & Tooling | Recorders, visualizers, sniffers, CLI, monitoring/observability integration | Debug When something is wrong, can I see it without writing code? |
For each category we name the most popular framework today, plus notable alternatives that differ on something you might care about. The Reach symbols mean:
Pick a concept from the dropdown for further discussion.
These two paradigms look similar — "data flowing from producer to consumer" — but they answer different questions.
flowchart LR
P[Publisher] -->|"topic /tick"| Bus(("Bus / Topic"))
Bus --> S1[Subscriber A]
Bus --> S2[Subscriber B]
Bus --> S3[Subscriber C]
flowchart LR
P[Producer] -->|"frame n, n+1, n+2 ..."| C[Consumer]
C -.->|"ack / credit"| P
The question is whether a separate process — the broker — sits in the middle of every conversation.
flowchart LR
P1[Publisher 1] --> B((Broker))
P2[Publisher 2] --> B
B --> S1[Subscriber 1]
B --> S2[Subscriber 2]
flowchart LR
P1((Peer 1)) --> P2((Peer 2))
P2 --> P1
P1 --> P3((Peer 3))
P3 --> P1
P2 --> P3
P3 --> P2
Most real systems are hybrid. Zenoh and DDS run brokerless on a LAN and add routers / discovery servers to bridge across WAN. Kafka has cluster brokers but clients talk directly to the leader broker per partition. The two designs aren't a religious choice — they're a knob you tune per network segment.
One support matrix per Comparison Dimension above. Pick a dimension from the dropdown to view its matrix.
Which communication shapes — pub/sub, request/reply, long-running action, streaming — the framework treats as first-class versus something you build on top with conventions.
| Framework | pub/sub | request/reply | long-running action | streaming |
|---|---|---|---|---|
| iceoryx | ✓ | △ | ✗ | ✓ |
| iceoryx2 | ✓ | ✓ | ✗ | ✓ |
| ZeroMQ | ✓ | ✓ | △ | ✓ |
| Fast DDS | ✓ | △ | △ | ✓ |
| Cyclone DDS | ✓ | △ | △ | ✓ |
| Zenoh | ✓ | ✓ | △ | ✓ |
| MQTT (Mosquitto) | ✓ | △ | ✗ | △ |
| Apache Kafka | ✓ | ✗ | ✗ | ✓ |
| gRPC | △ | ✓ | △ | ✓ |
| REST + OpenAPI | ✗ | ✓ | △ | △ |
| WebSocket | △ | △ | △ | ✓ |
Whether the framework is happiest with peers talking directly (brokerless), a central process in the middle (broker-centric), a mix of the two (hybrid), or a classic client-server split.
| Framework | brokerless | broker-centric | hybrid | client-server |
|---|---|---|---|---|
| iceoryx | ✓ | ✗ | ✗ | ✗ |
| iceoryx2 | ✓ | ✗ | ✗ | ✗ |
| ZeroMQ | ✓ | △ | ✗ | △ |
| Fast DDS | ✓ | ✗ | △ | ✗ |
| Cyclone DDS | ✓ | ✗ | △ | ✗ |
| Zenoh | ✓ | ✓ | ✓ | ✗ |
| MQTT (Mosquitto) | ✗ | ✓ | ✗ | ✗ |
| Apache Kafka | ✗ | ✓ | ✗ | ✗ |
| gRPC | ✗ | ✗ | ✗ | ✓ |
| REST + OpenAPI | ✗ | ✗ | ✗ | ✓ |
| WebSocket | ✗ | ✗ | ✗ | ✓ |
How far across the network the framework realistically reaches without bolting on extra gateways or routers — same host, same LAN, or across the public WAN.
| Framework | intra-host | LAN | WAN |
|---|---|---|---|
| iceoryx | ✓ | ✗ | ✗ |
| iceoryx2 | ✓ | ✗ | ✗ |
| ZeroMQ | ✓ | ✓ | ✓ |
| Fast DDS | ✓ | ✓ | △ |
| Cyclone DDS | ✓ | ✓ | △ |
| Zenoh | ✓ | ✓ | ✓ |
| MQTT (Mosquitto) | △ | ✓ | ✓ |
| Apache Kafka | ✗ | ✓ | ✓ |
| gRPC | ✓ | ✓ | ✓ |
| REST + OpenAPI | ✓ | ✓ | ✓ |
| WebSocket | ✓ | ✓ | ✓ |
Whether the framework forces you to define a separate wire-format file (and run a code generator) before any two parties can talk, or just moves opaque bytes and leaves the contract up to you.
| Framework | IDL | Approach |
|---|---|---|
| iceoryx | ✓ | Producer and consumer share the same C/C++ POD struct definition. No separate IDL file or codegen — the language type is the contract; the compiler enforces it. |
| iceoryx2 | ✓ | Producer and consumer share the same Rust / C++ / C type. No separate IDL file — the language type is the contract. |
| ZeroMQ | 🆓 | Opaque byte payload. You pick the serialization (JSON, protobuf, MsgPack, …) and document the wire format yourself. |
| Fast DDS | ✓ | .idl file + fastddsgen generates typed accessors and CDR serialization. Strict, compile-time enforced across languages. |
| Cyclone DDS | ✓ | .idl file + idlc generates typed accessors and CDR serialization. Strict, compile-time enforced across languages. |
| Zenoh | 🆓 | Opaque byte payload. Conventions only; pair with protobuf / CBOR / your own format if you want strictness. |
| MQTT (Mosquitto) | 🆓 | Opaque byte payload per topic. Documentation contracts only — many MQTT deployments use ad-hoc JSON. |
| Apache Kafka | △ | Bytes by default, but the Confluent Schema Registry (Avro / Protobuf / JSON Schema) is the de-facto contract layer in production deployments. |
| gRPC | ✓ | .proto file + protoc generates typed stubs and protobuf serialization. Strict, compile-time enforced across languages. |
| REST + OpenAPI | △ | JSON over HTTP by default; OpenAPI is widely used as an external schema and codegen source, but the runtime does not enforce it — you can always send arbitrary JSON. |
| WebSocket | 🆓 | Opaque text or binary frames. No schema layer in the protocol; bring your own (Socket.IO, JSON-RPC, custom). |
Whether each framework has an officially supported or widely-used mature library in the language. Niche or community-only bindings are not counted. For MQTT the row reflects the protocol's client ecosystem (paho-mqtt etc.), not the Mosquitto broker binary specifically.
| Framework | C++ | Python | JS/TS | Rust | Java | Go | C# | C | Swift |
|---|---|---|---|---|---|---|---|---|---|
| iceoryx | ✓ | ✓ | |||||||
| iceoryx2 | ✓ | ✓ | ✓ | ||||||
| ZeroMQ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Fast DDS | ✓ | ✓ | |||||||
| Cyclone DDS | ✓ | ✓ | ✓ | ||||||
| Zenoh | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ||
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Apache Kafka | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
| gRPC | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
| REST + OpenAPI | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| WebSocket | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Which class of timing the framework is engineered for. "Hard real-time" means bounded worst-case latency suitable for closing a control loop; "soft" means typical latency is low but the tail is not bounded; "best-effort" means latency is whatever the network and the GC give you.
| Framework | hard real-time | soft real-time | best-effort |
|---|---|---|---|
| iceoryx | ✓ | ✓ | ✗ |
| iceoryx2 | ✓ | ✓ | ✗ |
| ZeroMQ | ✗ | ✓ | ✓ |
| Fast DDS | ✓ | ✓ | ✓ |
| Cyclone DDS | ✓ | ✓ | ✓ |
| Zenoh | ✗ | ✓ | ✓ |
| MQTT (Mosquitto) | ✗ | ✗ | ✓ |
| Apache Kafka | ✗ | ✗ | ✓ |
| gRPC | ✗ | ✗ | ✓ |
| REST + OpenAPI | ✗ | ✗ | ✓ |
| WebSocket | ✗ | ✗ | ✓ |
Pieces typically required to run the framework in production. Read this matrix inverted from the others:
| Framework | extra daemon | central broker / cluster | IDL codegen step | TLS / cert setup |
|---|---|---|---|---|
| iceoryx | ✓ | |||
| iceoryx2 | ||||
| ZeroMQ | ||||
| Fast DDS | ✓ | |||
| Cyclone DDS | ✓ | |||
| Zenoh | ||||
| MQTT (Mosquitto) | ✓ | ✓ | ||
| Apache Kafka | ✓ | ✓ | ||
| gRPC | ✓ | ✓ | ||
| REST + OpenAPI | ✓ | |||
| WebSocket | ✓ |
Delivery guarantees the framework offers natively. Opting in usually still requires a config flag (e.g. RELIABLE in DDS, QoS 1/2 in MQTT, transactional producer in Kafka).
| Framework | at-most-once | at-least-once | exactly-once | ordering | history / durability | deadline / TTL |
|---|---|---|---|---|---|---|
| iceoryx | ✓ | ✓ | ✓ | |||
| iceoryx2 | ✓ | ✓ | ✓ | |||
| ZeroMQ | ✓ | ✓ | ||||
| Fast DDS | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Cyclone DDS | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Zenoh | ✓ | ✓ | ✓ | ✓ | ||
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Apache Kafka | ✓ | ✓ | ✓ | ✓ | ✓ | |
| gRPC | ✓ | ✓ | ||||
| REST + OpenAPI | ✓ | |||||
| WebSocket | ✓ | ✓ |
Whether the framework can be deployed on the platform without significant porting work. "Embedded RTOS" covers QNX, FreeRTOS, Zephyr, and similar.
| Framework | Linux | Windows | macOS | Android | iOS | Embedded RTOS | Browser / wasm |
|---|---|---|---|---|---|---|---|
| iceoryx | ✓ | ✓ | ✓ | ✓ | |||
| iceoryx2 | ✓ | ✓ | ✓ | ||||
| ZeroMQ | ✓ | ✓ | ✓ | ✓ | ✓ | ||
| Fast DDS | ✓ | ✓ | ✓ | ✓ | |||
| Cyclone DDS | ✓ | ✓ | ✓ | ✓ | |||
| Zenoh | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Apache Kafka | ✓ | ✓ | ✓ | ||||
| gRPC | ✓ | ✓ | ✓ | ✓ | ✓ | ||
| REST + OpenAPI | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| WebSocket | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Form-factors the framework realistically fits into — RAM, dependencies, build system all considered. "MCU / RTOS class" implies bare-metal or RTOS without a full POSIX environment; "embedded Linux" is e.g. Yocto / BuildRoot images.
| Framework | MCU / RTOS class | embedded Linux | edge / mobile | server / cloud |
|---|---|---|---|---|
| iceoryx | ✓ | ✓ | ✓ | |
| iceoryx2 | ✓ | ✓ | ✓ | |
| ZeroMQ | ✓ | ✓ | ✓ | |
| Fast DDS | ✓ | ✓ | ||
| Cyclone DDS | ✓ | ✓ | ✓ | |
| Zenoh | ✓ | ✓ | ✓ | ✓ |
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | ✓ |
| Apache Kafka | ✓ | |||
| gRPC | ✓ | ✓ | ✓ | |
| REST + OpenAPI | ✓ | ✓ | ✓ | ✓ |
| WebSocket | ✓ | ✓ | ✓ | ✓ |
How nodes find each other on bring-up. Multicast / mDNS works on a flat LAN but typically breaks across subnets and on Wi-Fi; static config and DNS scale further but require operator setup.
| Framework | static config | DNS | multicast / mDNS | discovery server / registry |
|---|---|---|---|---|
| iceoryx | ✓ | |||
| iceoryx2 | ✓ | |||
| ZeroMQ | ✓ | ✓ | ||
| Fast DDS | ✓ | ✓ | ✓ | |
| Cyclone DDS | ✓ | ✓ | ||
| Zenoh | ✓ | ✓ | ✓ | ✓ |
| MQTT (Mosquitto) | ✓ | ✓ | ||
| Apache Kafka | ✓ | ✓ | ✓ | |
| gRPC | ✓ | ✓ | ✓ | |
| REST + OpenAPI | ✓ | ✓ | ||
| WebSocket | ✓ | ✓ |
Whether the framework lets a late-joining subscriber receive past data, and how far back it can replay — in-memory only, on-disk durable log, or none at all.
| Framework | in-memory history | on-disk durable log | replay to late joiner | TTL / message expiry |
|---|---|---|---|---|
| iceoryx | ✓ | |||
| iceoryx2 | ✓ | |||
| ZeroMQ | ||||
| Fast DDS | ✓ | ✓ | ✓ | |
| Cyclone DDS | ✓ | ✓ | ✓ | |
| Zenoh | ✓ | ✓ | ✓ | ✓ |
| MQTT (Mosquitto) | ✓ | ✓ | ||
| Apache Kafka | ✓ | ✓ | ✓ | ✓ |
| gRPC | ||||
| REST + OpenAPI | ||||
| WebSocket |
Security primitives the framework provides out of the box. Many request/response stacks pick up "ACL / RBAC" and "signed identity" from a canonical companion layer (mTLS + OAuth/JWT) rather than from the wire protocol itself.
| Framework | TLS / mTLS | ACL / RBAC | payload-level encryption | signed identity |
|---|---|---|---|---|
| iceoryx | ||||
| iceoryx2 | ||||
| ZeroMQ | ✓ | ✓ | ✓ | |
| Fast DDS | ✓ | ✓ | ✓ | ✓ |
| Cyclone DDS | ✓ | ✓ | ✓ | ✓ |
| Zenoh | ✓ | ✓ | ✓ | |
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | |
| Apache Kafka | ✓ | ✓ | ✓ | |
| gRPC | ✓ | ✓ | ||
| REST + OpenAPI | ✓ | ✓ | ✓ | |
| WebSocket | ✓ | ✓ | ✓ |
Officially supported (or de-facto community standard) tools you can install today — what you reach for when something breaks and you need eyes on the wire.
| Framework | CLI | GUI viewer / monitor | recorder / replay | metrics / observability | official SDK docs |
|---|---|---|---|---|---|
| iceoryx | ✓ | ✓ | ✓ | ||
| iceoryx2 | ✓ | ✓ | |||
| ZeroMQ | ✓ | ||||
| Fast DDS | ✓ | ✓ | ✓ | ✓ | ✓ |
| Cyclone DDS | ✓ | ✓ | ✓ | ✓ | |
| Zenoh | ✓ | ✓ | ✓ | ✓ | |
| MQTT (Mosquitto) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Apache Kafka | ✓ | ✓ | ✓ | ✓ | ✓ |
| gRPC | ✓ | ✓ | ✓ | ✓ | |
| REST + OpenAPI | ✓ | ✓ | ✓ | ✓ | |
| WebSocket | ✓ | ✓ | ✓ |