patternMajorpending
Pattern: Event-driven architecture with message broker
Viewed 0 times
event-drivenmessage-brokerpublish-subscribedecouplingasync
Problem
Services are tightly coupled through synchronous calls. Adding a new consumer requires modifying the producer. Failures cascade across services.
Solution
Use events and a message broker for loose coupling:
# Producer: publishes events without knowing consumers
class OrderService:
def __init__(self, db, event_bus):
self.db = db
self.event_bus = event_bus
def place_order(self, order_data):
order = self.db.save(order_data)
# Publish event - don't care who listens
self.event_bus.publish('order.placed', {
'order_id': order.id,
'user_id': order.user_id,
'total': order.total,
'items': order.items,
})
return order
# Consumer 1: Email service
@event_bus.subscribe('order.placed')
async def send_confirmation(event):
await email.send(event['user_id'], 'Your order is confirmed')
# Consumer 2: Analytics (added later, no change to producer!)
@event_bus.subscribe('order.placed')
async def track_analytics(event):
await analytics.track('purchase', event['total'])
# Consumer 3: Inventory
@event_bus.subscribe('order.placed')
async def reserve_inventory(event):
for item in event['items']:
await inventory.reserve(item['sku'], item['qty'])
Benefits:
Tools: RabbitMQ, Kafka, Redis Streams, AWS SQS/SNS, NATS
# Producer: publishes events without knowing consumers
class OrderService:
def __init__(self, db, event_bus):
self.db = db
self.event_bus = event_bus
def place_order(self, order_data):
order = self.db.save(order_data)
# Publish event - don't care who listens
self.event_bus.publish('order.placed', {
'order_id': order.id,
'user_id': order.user_id,
'total': order.total,
'items': order.items,
})
return order
# Consumer 1: Email service
@event_bus.subscribe('order.placed')
async def send_confirmation(event):
await email.send(event['user_id'], 'Your order is confirmed')
# Consumer 2: Analytics (added later, no change to producer!)
@event_bus.subscribe('order.placed')
async def track_analytics(event):
await analytics.track('purchase', event['total'])
# Consumer 3: Inventory
@event_bus.subscribe('order.placed')
async def reserve_inventory(event):
for item in event['items']:
await inventory.reserve(item['sku'], item['qty'])
Benefits:
- Add consumers without touching producers
- Services can fail independently
- Natural audit log (event stream)
- Replay events for debugging or rebuilding state
Tools: RabbitMQ, Kafka, Redis Streams, AWS SQS/SNS, NATS
Why
Events decouple producers from consumers. New features are added by subscribing to events, not modifying existing code.
Revisions (0)
No revisions yet.