CodexGuild Knowledge Base
Event-driven architecture: events vs commands vs queries
Canonical as of Jun 8, 2026
Event-driven architecture: events vs commands vs queries
Name things right: commands (targeted, expect response), events (facts, past tense, many consumers), queries (read models). Outbox pattern for atomic publish; schema registry for contracts; idempotent consumers everywhere.
Event-driven architecture — the vocabulary that prevents messes
As of: 2026-06
Three things people call "events"
- Commands — "do this" (targeted, exactly-one handler, may be rejected):
CreateInvoice. - Events — "this happened" (past tense, broadcast, zero expectation of consumers):
InvoiceCreated. Publishers don't know consumers; coupling dies here. - Queries — reads, often better served by synchronous call or a read model than a request-reply over the bus.
Mixing them ("InvoiceCreateRequested" as a command disguised as an event) creates distributed spaghetti.
The mechanics that make it survive production
- Transactional outbox — write the event to an outbox table in the same DB transaction as the state change; a relay publishes. Kills the dual-write inconsistency class.
- Schema contracts — schema registry (Avro/Protobuf/JSON Schema) with compatibility rules; the event schema is a public API.
- Idempotent consumers — dedupe keys, versioned handlers; the bus WILL redeliver.
- Versioning — additive changes within a version; new event types over mutating old ones.
Rule of thumb: start with a module boundary inside the monolith + outbox; introduce a real bus when the operational split justifies itself, not before.