Real World Example

Order Events at a Quick-commerce Company

Quick-commerce apps (Zepto, Blinkit, Swiggy Instamart) publish every order state change to Kafka. Many services react independently, so adding a new feature (for example loyalty points) means adding a consumer, not changing the orders service.

orders-service  --emit-->  Kafka topic "order.events"
                              |-- dark-store-service    : start picking
                              |-- rider-service         : assign nearest rider
                              |-- notifications-service : push + SMS
                              |-- loyalty-service       : add coins
                              '-- analytics-service     : BigQuery

apps/loyalty/src/loyalty.controller.ts

import { Controller, Logger } from '@nestjs/common';
import { Ctx, EventPattern, KafkaContext, Payload } from '@nestjs/microservices';

interface OrderEvent { type: 'ORDER_DELIVERED' | 'ORDER_CANCELLED'; orderId: string; userId: number; total: number }

@Controller()
export class LoyaltyController {
  private readonly logger = new Logger(LoyaltyController.name);

  constructor(private readonly loyalty: LoyaltyService) {}

  @EventPattern('order.events')
  async handle(@Payload() event: OrderEvent, @Ctx() ctx: KafkaContext) {
    if (event.type !== 'ORDER_DELIVERED') return;
    // idempotent: the same Kafka message may be delivered twice
    const added = await this.loyalty.addCoinsOnce(event.orderId, event.userId, Math.floor(event.total / 100));
    this.logger.log(`partition ${ctx.getPartition()} offset ${ctx.getMessage().offset}: +${added} coins for user ${event.userId}`);
  }
}