Asynchronous messaging

Microservices · lesson 4 of 33 · 4 min read

Use events so a slow or dead consumer cannot take the producer down with it.

Open this lesson in the learning hub

Key points

  • Async means the producer writes a message and moves on. The consumer catches up later, or after a restart.
  • Publish facts, not commands. OrderPlaced lets new consumers subscribe later; SendEmail wires in just one.
  • Kafka keeps an ordered, replayable log per partition. RabbitMQ routes and drops once acked. Choose replay or routing flexibility.
  • Delivery is at least once, so duplicates are guaranteed eventually. Consumers must be idempotent (two lessons on).
  • Async buys availability and costs certainty. There is no instant answer, only "it will be consistent shortly".

Example

record OrderPlaced(String orderId, String sku, int qty, Instant at) {}

@Component
class OrderEvents {

    private final KafkaTemplate<String, OrderPlaced> kafka;

    OrderEvents(KafkaTemplate<String, OrderPlaced> kafka) { this.kafka = kafka; }

    void publish(OrderPlaced event) {
        // Key by orderId: same key -> same partition -> ordered per order.
        kafka.send("orders.placed", event.orderId(), event);
    }
}

@Component
class InventoryListener {

    @KafkaListener(topics = "orders.placed", groupId = "inventory")
    void on(OrderPlaced event) {
        // Redelivered if we crash before the offset is committed.
        // So this must be safe to run twice with the same event.
        reserve(event.orderId(), event.sku(), event.qty());
    }
}

Events decouple services in time: the producer keeps working when the consumer is down.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Microservices course, and every lesson in it is listed on the Microservices contents page.