An in-process event can loosen module coupling, but publication alone does not guarantee durable external delivery.
Spring Modulith events: publish a domain fact after a valid state change
Name a committed fact
Inventory can publish ReceiptReserved after recording a successful reservation. Dispatch listens for that fact instead of reading inventory.internal. A failed version check must emit no successful event. Transaction event timing determines when a listener sees committed state; the outbox records an external delivery intent with the state change.
Account for listener failure
A synchronous listener can fail the publisher; an asynchronous one can fail after the caller returns. Spring Modulith's publication registry can persist outstanding transactional-listener publications when installed and configured. That is not identical to Kafka acceptance. The isolated module slice now checks in-process publication for an accepted reservation and silence for a rejected one. Registry persistence and restart remain untested.
Boundary sketch
record ReceiptReserved(String tenantId, String receiptId,
int units, long version) {}
// Publish only after the guarded reservation decision succeeds.Cost and verification
Events reduce direct package coupling but add ordering, duplicate and recovery decisions. A persisted registry adds database writes per publication. This sketch is not executed by the source kit.
Common Mistakes
- Do not publish a successful domain event before a valid state change.
- Do not call an in-process event a durable queue.
- Do not assume a broker send rolls back with the database.
Read next
Spring Modulith module APIs: call the inventory root package, not its internals, Spring Modulith module tests: distinguish structure verification from a sliced context, Spring transaction events: run a listener after commit without claiming durability, Spring transactional outbox: commit a receipt and event row together.
Checked publication and remaining delivery
See the in-process event test, then the untested registry recovery boundary.
