Pub/Sub Pattern
debt(d8/e7/b7/t7)
Closest to 'silent in production until users hit it' (d8), detection_hints.automated is no — missed events from offline subscribers using Redis SUBSCRIBE only surface when users notice missing behavior, slightly better than d9 because code review can flag SUBSCRIBE usage.
Closest to 'cross-cutting refactor across the codebase' (e7), quick_fix says switch from Redis SUBSCRIBE to Redis Streams or Kafka — that's a broker swap touching every publisher and subscriber, plus redesigning events to be idempotent and self-contained.
Closest to 'strong gravitational pull' (b7), applies_to spans web/cli/queue-worker — once event-driven decoupling is adopted, every feature is shaped by the publish/subscribe contract and topic design.
Closest to 'serious trap' (t7), misconception explicitly says devs conflate pub/sub with queues, and Redis SUBSCRIBE 'looks like' durable pub/sub but silently drops messages for offline subscribers — contradicts the mental model of queues.
TL;DR
Explanation
Publisher sends to a Topic/Channel — it doesn't know who's listening. Subscribers declare interest in topics. Broker delivers to all active subscribers. Implementations: Redis PUBLISH/SUBSCRIBE, Kafka topics, RabbitMQ fanout exchange, SNS+SQS (AWS), Google Pub/Sub. Difference from point-to-point queue: queue delivers to ONE consumer; pub/sub delivers to ALL subscribers. Use cases: event broadcasting (user registered → email + analytics + audit + recommendation all receive it), real-time feeds (dashboard updates). Fan-out: one event → many independent handlers. Redis pub/sub doesn't persist — subscribers miss messages while offline; use Redis Streams for durability.
Common Misconception
Why It Matters
Common Mistakes
- Using Redis SUBSCRIBE for durable events — messages are lost if subscriber is offline.
- Publishing events that are too granular — hundreds of tiny events create consumer overhead.
- Not considering message ordering when multiple publishers write to the same topic.
Code Examples
// Redis SUBSCRIBE — volatile, lost if offline:
$redis->subscribe(['user.registered'], function($redis, $channel, $msg) {
sendWelcomeEmail($msg); // Missed if worker was down during publish
});
// Redis Streams — durable pub/sub:
$redis->xadd('user.events', '*', ['event' => 'registered', 'user_id' => $id]);
// Consumer group reads with acknowledgement:
$msgs = $redis->xreadgroup('email-group', 'worker-1', ['user.events' => '>']);
foreach ($msgs['user.events'] as $id => $fields) {
sendWelcomeEmail($fields['user_id']);
$redis->xack('user.events', 'email-group', $id);
}