Problem
booking-service commits booking state in PostgreSQL and only then publishes Redis Streams events. If the process crashes or Redis is unavailable after the DB commit, downstream services never see the booking event.
Evidence
apps/bot/services/booking-service/src/booking-router.ts:412 commits the booking transaction through createBookingTransaction.
apps/bot/services/booking-service/src/booking-router.ts:415 publishes STREAMS.BOOKING_CREATED after the transaction has already completed.
apps/bot/services/booking-service/src/booking-router.ts:566 updates booking status in PostgreSQL.
apps/bot/services/booking-service/src/booking-router.ts:578 publishes STREAMS.BOOKING_CANCELLED after the status update.
Impact
A booking can exist in the database while notification, analytics, calendar sync, or other consumers never receive the matching event. This creates silent data divergence.
Expected Fix
Implement a transactional outbox for booking events:
- write an outbox row in the same PostgreSQL transaction as the booking mutation;
- publish from an outbox worker after commit;
- include a stable
eventId for consumer idempotency;
- retry failed publishes and expose failed outbox rows for replay.
Problem
booking-servicecommits booking state in PostgreSQL and only then publishes Redis Streams events. If the process crashes or Redis is unavailable after the DB commit, downstream services never see the booking event.Evidence
apps/bot/services/booking-service/src/booking-router.ts:412commits the booking transaction throughcreateBookingTransaction.apps/bot/services/booking-service/src/booking-router.ts:415publishesSTREAMS.BOOKING_CREATEDafter the transaction has already completed.apps/bot/services/booking-service/src/booking-router.ts:566updates booking status in PostgreSQL.apps/bot/services/booking-service/src/booking-router.ts:578publishesSTREAMS.BOOKING_CANCELLEDafter the status update.Impact
A booking can exist in the database while notification, analytics, calendar sync, or other consumers never receive the matching event. This creates silent data divergence.
Expected Fix
Implement a transactional outbox for booking events:
eventIdfor consumer idempotency;