Skip to content

Data Flow

This page covers the three main runtime flows: search, booking creation, and cancellation/rescheduling. Each flow is illustrated with the relevant diagram and a step-by-step description.


Search Flow

A patient query traverses two hops: the Search Service for filtering practitioners, then the Availability Service to resolve exact open slots for a selected practitioner.

Patient → ALB → Search Service → OpenSearch (geo + specialty + availability filter)
  → Returns ranked practitioner list with next_available_slot

Patient selects practitioner → ALB → Availability Service → Redis bitmap
  → Returns exact available time slots for the chosen date range

OpenSearch query structure: A single compound query combines: - geo_distance filter on practitioner location - term filter on specialty - range filter on next_available_slot - Relevance scoring by distance and rating

Redis bitmap lookup: Each practitioner/day pair maps to a 24-bit integer (one bit per hour slot). The Availability Service decodes this into a list of open times in O(1).


Booking Flow

Booking Flow

The booking flow is designed for strong consistency on the write path while keeping read-path latency low via Redis pre-checks.

Step-by-step:

  1. Patient → ALB → Booking Service — patient submits a booking request for a specific practitioner/slot.
  2. Redis pre-check — Booking Service queries the availability bitmap to confirm the slot is likely free. This short-circuits obvious conflicts before hitting the database, reducing lock contention under load.
  3. INSERT into RDS — the unique partial index (idx_no_double_book) is the definitive conflict gate. If two concurrent requests pass the Redis check, only one INSERT succeeds.
  4. Publish BookingCreated → MSK — the event is produced to the booking-events topic, partitioned by practitioner_id to guarantee per-practitioner ordering.
  5. Availability Service consumes BookingCreated → marks the Redis bitmap slot as booked → publishes AvailabilityChanged to availability-events.
  6. Search Service consumes AvailabilityChanged → updates the next_available_slot field in the practitioner's OpenSearch document.
  7. Notification Service consumes BookingCreated → sends confirmation email (SES) and SMS/push (SNS) to both patient and practitioner.

Redis pre-check is an optimisation, not a lock

The pre-check reduces database round-trips under contention but does not prevent double-booking on its own. The database constraint is the authoritative gate. See ADR-004.


Cancellation and Rescheduling Flow

Cancel and Reschedule Flow

Cancellations use optimistic concurrency via a version column on the bookings table. The UPDATE includes a WHERE version = $current_version clause; if another write raced ahead, the update affects zero rows and the client retries.

Cancellation step-by-step:

  1. Patient → ALB → Booking Service — patient submits a cancellation for booking ID N.
  2. UPDATE bookings SET status = 'cancelled', version = version + 1 WHERE id = N AND version = $v — optimistic lock. Zero rows updated = conflict, client retries.
  3. Publish BookingCancelled → MSK (booking-events, partitioned by practitioner_id).
  4. Availability Service consumes BookingCancelled → clears the Redis bitmap slot → publishes AvailabilityChanged.
  5. Search Service consumes AvailabilityChanged → updates next_available_slot in OpenSearch (slot is now free).
  6. Notification Service consumes BookingCancelled → sends cancellation confirmation to patient and practitioner.

Rescheduling is implemented as a cancellation of the old booking followed by a new booking creation. Both operations are wrapped in a single RDS transaction to prevent a gap where the slot appears free between the cancel and re-book.


Event Flow / Kafka Topology

Event Flow

The diagram above shows the full Kafka topology: which services produce to which topics, and which services consume from each topic.

Topics:

Topic Producers Consumers
booking-events Booking Service Availability Service, Notification Service
availability-events Availability Service Search Service
practitioner-events Practitioner Service Search Service, Availability Service

Key configuration:

  • Partitioned by practitioner_id for per-practitioner ordering guarantees
  • Replication factor 3; min in-sync replicas 2 — survives single broker loss
  • 7-day / 168-hour retention — enables full replay to rebuild read models (OpenSearch indices, Redis bitmaps)
  • 6 partitions per topic by default

Read model recovery via Kafka replay

If the OpenSearch cluster or Redis is lost, both can be fully rebuilt by replaying the 7-day Kafka log. This eliminates the need for a separate backup/restore procedure for these derived stores.