In a request and response system, the arrows on the diagram are the call graph. In an event-driven system they are not. A producer writes an event to a topic and does not know who reads it. Draw that naively, every service connected to one big Kafka box, and the diagram hides everything you need: which events exist, who reacts to them, in what order, and what happens when a consumer fails.
This guide gives you a notation for event-driven architecture diagrams that keeps the flow readable, walks through an order processing example on Kafka, and covers the details people forget to draw: keys, consumer groups, the outbox and the dead-letter path.
What the diagram has to show
An event-driven diagram should answer these questions without a separate document:
- Which events exist? Named in the past tense, such as
OrderPlacedorPaymentFailed. - Who produces each one? Exactly one owner per event type is the healthy default.
- Who consumes it, and as which consumer group? In Kafka every consumer group gets every event, so each group is a separate reader.
- What decides ordering? Kafka keeps order only within a partition, and the key picks the partition.
- What happens on failure? Retries, dead-letter topics, and who replays.
A notation that works
| Element | How to draw it |
|---|---|
| Producer | A service node with a dashed edge to the topic, labeled with the event type |
| Topic | Its own node, named as in the cluster (orders.v1), with the key in the label |
| Consumer group | A dashed edge from the topic to the consumer, labeled with the group id |
| Event vs command | Events in the past tense (OrderPlaced), commands in the imperative (ReserveStock) |
| Dead-letter topic | A separate topic node, fed by the consumer that gave up |
| Connector | A node between a topic and an external store, such as a warehouse sink |
| Broker cluster | A frame around the topics; brokers and partitions go on the ops diagram |
Use solid edges only for synchronous calls, such as an HTTP request to a payment provider. Then a reader can tell at a glance which parts of a flow happen in the same request and which happen later.
The example: order events on Kafka
An online store processes orders with events:
- The orders service writes the order and an outbox row in the same database transaction.
- An outbox relay (Debezium on Kafka Connect) reads the outbox through the database log and publishes
OrderPlacedtoorders.v1, keyed byorder_id. - Three consumer groups read
orders.v1: payments charges the card, inventory reserves stock, and a warehouse sink loads every event into the data warehouse. - Payments publishes
PaymentSucceededorPaymentFailedtopayments.v1, also keyed byorder_id, and the orders service consumes it to update the order status. - When inventory cannot process a message after three attempts, it writes the message to
inventory.dlqand moves on.
Here is the whole flow on one canvas:
Diagram contents
- Orders
- Orders DB (orders + outbox)
- Outbox relay
- Kafka cluster
- payments.v1 · key order_id
- orders.v1 · key order_id
- inventory.dlq
- Payments
- Warehouse sink
- Inventory
- Data warehouse
- order + outbox row, one transaction
- reads WAL
- OrderPlaced
- group: payments
- group: warehouse-sink
- group: inventory
- PaymentSucceeded/Failed
- group: orders
- load
- after 3 failed attempts
Notice what the diagram makes obvious: nobody calls payments, adding a fourth consumer group changes nothing upstream, and events for one order stay in order within each topic because both are keyed by order_id (Kafka gives no ordering across topics).
Five rules for event-driven diagrams
1. Topics are nodes, not arrows
An arrow from orders to payments labeled "Kafka" suggests a call that does not exist. Draw the topic as a node between them. It is a real thing with a name, an owner, a retention period and a schema.
2. Arrows follow the data
Draw producer to topic to consumer, in the direction the data moves. Kafka consumers pull, but a diagram that points arrows from consumers to topics reads backwards to almost everyone. If pull semantics matter for the discussion, add a note.
3. Label events and consumer groups
Put the event type on the producer edge and the consumer group on each consumer edge. When someone asks "who else reads OrderPlaced?", the answer is the list of labeled edges leaving the topic.
4. Show the key when ordering matters
Kafka guarantees order within a partition, and events with the same key go to the same partition. If your consumers rely on seeing OrderPlaced before OrderCancelled, write the key on the topic: orders.v1 · key order_id. A topic without a key in the label invites the question.
5. Draw the unhappy path
Kafka consumer groups have no built-in dead-letter queue: your consumer code or framework decides how many times to retry and where to put a message it cannot process (Kafka Connect sink connectors do have a dead-letter topic setting). Draw that decision. A dead-letter topic with an edge from the consumer, and a note on who watches it and how messages get replayed, saves an incident.
Draw the outbox, not the shortcut
If a service writes to its database and then publishes to Kafka in two separate steps, a crash between them loses an event or publishes one for a change that never committed. The outbox pattern avoids that dual write: the service writes the event to an outbox table in the same transaction, and a relay publishes it.
On the diagram, draw the real path: service to database to relay to topic. A direct arrow from the service to the topic would describe a different, less reliable system, and people will make decisions based on it.
Choreography or orchestration
The example uses choreography: services react to each other's events, and no one is in charge of the whole flow. If you use an orchestrator instead, a workflow engine that sends commands such as ReserveStock and waits for replies, draw the orchestrator as a service in the middle and label its edges as commands. Either way, number the steps of the main flow on the edges so readers can follow the saga in order.
Keep the cluster out of the logical view
Brokers, partitions, replication factors and controller nodes matter for capacity and operations, not for understanding the flow. Put them on a separate ops diagram. On the logical view, a frame labeled "Kafka cluster" around the topics is enough.
Build it in Archboard
- Sign in with Google or GitHub and create a diagram.
- Add the services as Container nodes from the C4 Model pack, and the orders database from the Data pack (Postgres).
- Add a Core Frame labeled
Kafka clusterand put Topic nodes from the Data pack inside it. - Add the outbox relay and the warehouse sink as containers with
Kafka Connectin the technology field, and a Data Warehouse node from the Data pack. - Connect ports, set event edges to a dashed line, and label them with event types and consumer groups.
- Open it in presentation mode for the review, share the live link, or export SVG and PNG.
The example uses 11 diagram nodes, within the Free plan's 15. For another streaming layout, see /examples/streaming-data-platform, and for the synchronous side of a similar store, the microservices architecture diagram guide.
FAQ
Should I draw partitions? Not on the logical view. Write the partition count in the topic label if it matters, and draw partitions and brokers on an ops diagram.
How is a queue different from a topic on the diagram? In a queue, each message goes to one consumer; in a Kafka topic, each consumer group gets every message. Use a Queue node for queues such as SQS or RabbitMQ, and say which semantics you rely on.
Where do event schemas go? In a note or the topic label, with a link to the schema registry or the repository that owns the schema. The diagram should show that a contract exists and where it lives.
How do I show replay?
Write the retention on the topic (for example retention 7d) and add a note on how a consumer group resets its offsets. Replay is a design feature; make it visible.
Do I need one diagram per event? No. One diagram per business flow works well. List the events on the edges, and keep an event catalog for the full list.