Architecture

All notifications flow through a job queue and are delivered via a primary/fallback provider pattern.

Primary Delivery Flow

Application Background Job Queue WAHA (Primary) Customer WhatsApp

Fallback Delivery Flow

WAHA fails Twilio (Fallback) Customer WhatsApp

WAHA (Primary)

Self-hosted WhatsApp HTTP API. Zero per-message cost. Runs as a Docker container alongside the application. All notifications attempt WAHA first.

Twilio (Fallback)

Automatic fallback when WAHA delivery fails after all retry attempts. Per-message cost, but guarantees delivery when the primary channel is down.

Background Job Queue (Hangfire or IHostedService)

Never send notifications synchronously. Every notification is enqueued as a background job via Hangfire or a .NET IHostedService. This decouples booking creation from message delivery and enables retries.

Delivery Status Webhooks

WAHA sends delivery status callbacks via webhooks. The system tracks each message from pending through delivered or failed.

4 Core Templates

All templates are written in Arabic. Each template uses variable interpolation for customer and booking details.

Template Trigger When
booking_created Booking is created Immediately
booking_confirmed Status changes to confirmed On confirmation
24h_reminder 24 hours before session Scheduled job
booking_cancelled Booking is cancelled Immediately

Template Variables

Every template has access to the following variables, injected at send time:

Variable Description Example
customer_name Customer's display name Ahmed
field_name Name of the booked field (Arabic) ملعب 1
location_name Location name (Arabic) ملاعب النجمة
date Booking date 2024-03-15
time Session start time 18:00
price Booking price in SAR 150 SAR
All templates are in Arabic. Template content is stored in the notification_templates table with name_ar and body_ar columns. Variables are interpolated using placeholder syntax within the Arabic text.

Delivery Status Tracking

Happy Path

pending sent delivered

Failure Path

pending sent failed retry up to 3 attempts via WAHA, then fallback to Twilio
Status Meaning
pending Queued, not yet sent
sent Sent to provider (WAHA or Twilio)
delivered Confirmed delivered to recipient
failed Delivery failed after all retries

Webhook Endpoints

Two webhook endpoints receive callbacks from WAHA:

Method Endpoint Purpose
POST /webhooks/whatsapp/messages Incoming messages from customers via WAHA
POST /webhooks/whatsapp/status Delivery status updates from WAHA

Retry Logic

Attempt Provider Delay
1st attempt WAHA Immediate
2nd attempt WAHA 30 seconds
3rd attempt WAHA 2 minutes
4th attempt (fallback) Twilio 10 minutes
Never silently drop a notification. Every failure must be logged with the error code, provider, and template. Failed notifications surface in admin analytics for manual follow-up.

Incoming Messages (Future)

Post-launch feature: For v3 launch, incoming messages are stored in the incoming_messages table but not processed automatically. Bidirectional WhatsApp (auto-responses, booking confirmation via reply) is a post-launch feature.

The incoming_messages table captures:

Analytics Events

The following PostHog events are dispatched for notification tracking:

Event Properties
notification_sent template, channel, provider
notification_delivered template, delivery_time_ms
notification_failed template, error_code, provider
customer_message_received is_reply, contains_booking_ref