Request-Reply and Fire-and-Forget
The two interaction shapes available between components, differing in whether the caller waits for a result and therefore in whether availability compounds.
Request-reply (synchronous): the caller waits. Simple to reason about, immediate error handling, straightforward debugging — and it creates temporal coupling, so the callee's availability multiplies into the caller's. Ten dependencies at 99.9% give 99.0%.
Fire-and-forget (asynchronous): the caller hands off work and continues. The callee may be down; the work still completes later. Load is smoothed by the queue, and new consumers can be added without touching the producer.
The costs of asynchrony are real and should be stated rather than glossed: eventual consistency, harder debugging (causation is separated in time), at-least-once delivery requiring idempotent consumers, and the need for a way to report failures that occur after the caller has gone.
The decision rule that works: does the caller need the result to continue? A price quote does. Sending a confirmation email does not. An inventory check before accepting an order does; updating a recommendation model does not.
Most systems are more synchronous than necessary because request-reply is the default in every framework. Converting a call to an event is frequently the highest-leverage availability change available, because it removes a dependency from the series entirely rather than making it more reliable.