Skip to content
About
Main content

Eight transports on three switches

A transport is the thing that sits between a and a consumer that have independent rates, availability and lifetimes. Every pattern below is a specific purchase of decoupling along those three dimensions, plus a specific answer to four consequential questions:

  1. Who holds the record between send and process? (the sender, a broker, a network buffer, or nobody)
  2. Who holds the progress state? ("how far have we got?": the broker per message, the consumer per stream, or nobody)
  3. What survives a crash on either side?
  4. What order is preserved, and over what scope?

Answer these four for any transport and you have characterized it. Everything else (protocol, vendor, API shape) is detail.

The lattice: eight patterns on the three switches

PatternRate decoupledAvailability decoupledIdentity decoupledProgress state lives
Sync / request-responsenonononowhereno
partial (credits)nonothe connectionno
(UDP)nonoyesnowhereno (only gap filling)
In-memory yes (bounded)nopartialbroker (volatile)no
Durable queueyesyespartialbroker, per messageno
over durable queuesyesyesyesbroker, per subscriberno
Append-only logyesyesyesconsumer (an )yes
Bulk file transferyes (unbounded)yesyesfilesystem / file namingyes

Replay means reading the same records again after they were already processed once.

Two things fall straight out of this table.

First: the durability column and the replay column are not the same thing. A durable queue survives a broker restart, but it cannot give you the record back once it is acknowledged. Durability protects against a crash. (keeping records for a period) protects against being wrong. Most teams buy the first and discover a year later that they needed the second. This is Lena's first problem exactly.

Second: the "identity decoupled" column is what makes a system extensible. You can add a consumer without touching the producer. This is what people actually mean by "loosely coupled", and it is cheaper than they think: it costs an addressing indirection (a name) and nothing else. The expensive decoupling is availability, because that one requires storage.

Primitives, composites and shapes

A common list of "transport patterns" mixes three levels:

  • Primitives (irreducible; each is a real decision): the append-only log, the queue, request/response, push versus pull.
  • Composites (a primitive plus a policy; learn them as derivations, not as equals): publish/subscribe, , streaming replication, change feeds, , RPC variants, .
  • Shapes (descriptions of how many senders and receivers, which apply to any of the above): , fan-out, broadcast/multicast.

So there are four things to understand deeply, and then a set of derivations. We follow that order.