--- topic: the mesh status: accepted date: 2026-09-26 deciders: jochen reconstructed: false supersedes: 02-DECISIONS/0117-the-bus-is-the-only-broker.md --- # 119. AMQP is a provision, not the bus ## Context [ADR 0117](0117-the-bus-is-the-only-broker.md) decided that the bus is the only broker, and went one step further than it had grounds for: it also decided that the `amqp` **interface** — a module requiring a message broker of its own — "is not carried forward" and "retires with the compatibility broker rather than gaining a successor", with the two modules declaring it converted to the bus in step 4. The operator's correction: **AMQP is deprecated as the mesh's transport, not abolished as a service.** The broker module keeps running and keeps answering `amqp` requirements. It is no longer a core part of the mesh — *"it's just a module like mssql now."* **What 0117 conflated** is two different reasons a module might ask for a broker, which look identical in a manifest: 1. **To talk to other modules.** Wrong under one bus, and the thing 0117 was right to refuse: a private broker used as inter-module transport is a second bus, with every guarantee crossing a seam and no scoping the mesh can see. 2. **Because it genuinely needs an AMQP broker**, the way something needs a database — a queue for its own internals, or interop with software that speaks AMQP and nothing else. That is a backing service, and the mesh has a word for backing services already. 0117 saw the first and legislated against both. The second is ordinary, and forbidding it would make the mesh unable to run a large class of perfectly normal software while claiming that as architecture. ## Considered Options 1. **Keep 0117 as written** — retire the interface, convert the two modules. Rejected by the operator, and wrongly reasoned besides: it treats "needs an AMQP broker" as always a mistake. 2. **Keep the broker as the predecessor's compatibility module**, as ADR 0106 framed it, with a retirement condition. Rejected: it is not single-purpose and its clients are not only the predecessor's, so the retirement condition describes a day that will not come. 3. **The broker is an ordinary provider module of an ordinary provision.** Adopted. ## Decision **The mesh's bus is NATS and only NATS.** Everything 0117 decided about *the bus* stands: one bus, a module's messaging is subjects on it scoped by what it declares, no module is handed a bus of its own, and the `mesh-broker` seat is the NATS server's. **`amqp` remains a provision a module may require**, answered by the broker module the way `postgres-database` is answered by the store module or a database is answered by mssql. It is not deprecated as an interface; the software behind it is simply no longer the mesh's nervous system. **The broker module stops being foundation.** It claims no seat — `mesh-broker` is the NATS server's — it is not raised at genesis, nothing in the mesh requires it, and a mesh that never installs it is a complete mesh. It is installed when something wants it, like any other provider. **The rule that survives, stated so it can be applied:** *inter-module communication goes over the bus.* A module may hold a broker, a database or a cache as a backing service; it may not use one as a channel to another module. The line is not which software is involved, it is whether a second module is on the other end. **Neither `amqp-ping` nor `amqp-email-forwarder` needs converting.** 0117 put that work in step 4; it is removed. They require a backing service and a provider answers. ## Consequences - **The "compatibility broker" framing is wrong and goes.** There is no `lavinmq-compat`, no single purpose and no retirement condition. Design 25 §5 is corrected. - **[ADR 0106](0106-the-bus-is-nats.md)'s progressive insight was itself wrong** and is corrected by a second one there. It said 0117 would make 0106's "one purpose — the predecessor's clients" sentence true by moving the mesh's modules off. Nothing moves off; the sentence is simply not what the broker is. - **The seat change stands**, for a better reason than 0117 gave: not because a broker cannot be provisioned, but because *this* broker is not the mesh's bus. The broker module drops its `mesh-broker` claim and the `nats` module takes it. - **Step 4 loses two conversions**; step 1 and the WBS are otherwise unaffected. - **What got harder:** the rule is now a judgement rather than a prohibition. "Is this a backing service or a channel to another module?" has to be asked in review, where 0117 could have answered it with a parser. That is the honest cost of allowing the legitimate case. ## How it is checked - **A module's own messaging needs no `requires`.** The check from 0117, unchanged: a module declaring only `emits` and `consumes` reaches its subjects and is refused every other. - **The broker holds no seat.** A manifest test: the broker module claims nothing, and a mesh raised without it is complete — genesis names it nowhere. - **`amqp` resolves like any provision.** A resolution test: a module requiring it is answered by the provider, refused when none is assigned, and neither case touches the bus. - **What cannot be checked mechanically**, and is said rather than implied: that a module holding a broker is not using it to reach another module. Review, not a parser. ## References - [ADR 0117](0117-the-bus-is-the-only-broker.md) — superseded; its ruling on the bus is kept whole and only its ruling on the interface is reversed. - [ADR 0106](0106-the-bus-is-nats.md) — the bus is NATS; its compatibility-broker framing is corrected here. - [ADR 0118](0118-a-module-declares-its-own-seats.md) — seats, including the one the NATS server now holds alone.