5.5 KiB
Proposal: Notification System Redesign
Intent
The current notification system has three critical limitations: (1) notifications are sent synchronously during appointment lifecycle operations, blocking the API response; (2) the notification-sender worker only handles today's appointments with a global delay (no per-company throttling for WhatsApp rate limits); and (3) there are no per-company or per-client notification preferences — notifications are either on or off for the entire company. This redesign decouples notification delivery from business operations into a job-based, multi-channel, policy-driven system.
Scope
In Scope
- New
NotificationJobmodel: per-notification job records with status, channel, payload, retry state - New
CompanyNotificationPolicymodel: org-level defaults for channels, scheduling windows, WhatsApp throttle config - New
ClientNotificationPreferencesmodel: per-client opt-in/out per channel - New
ClientCompanyNotificationOverridemodel: per-client per-org overrides - Policy resolution engine: Plan limits → Org override → Client prefs → Org default → System default
- Redesigned notification-sender worker: MongoDB polling, per-company WhatsApp throttle (8–16s), multi-channel dispatch
- Server integration: replace inline notification calls in
Appointmentswith job creation - Multi-channel support: WhatsApp (Baileys), Email (DonWeb), System (in-app + Socket.IO)
Out of Scope
- SMS channel (plan feature exists but not implemented today)
- Notification templates / content builder
- Client-facing notification preferences UI
- Notification analytics / delivery reports
- Push notifications (mobile)
- Batch notification operations (e.g., "notify all clients about holiday")
Capabilities
New Capabilities
notification-jobs: Job creation, status tracking, retry logic, and lifecycle management for notification deliverynotification-policies: Company and client notification preferences, policy resolution hierarchy, channel configurationnotification-worker: Multi-channel job processor with per-company throttling and MongoDB pollingnotification-integration: Server-side hooks that create notification jobs from appointment lifecycle events
Modified Capabilities
None — no existing specs in openspec/specs/.
Approach
Server (job creation): Replace inline NotificationsManager.send*() calls in Appointments.ts with NotificationJobService.createJob(). The service resolves the effective policy, checks plan limits, and persists a NotificationJob document. This makes API calls non-blocking.
notification-sender (worker): Poll MongoDB for status: "pending" jobs. Process per-company with configurable WhatsApp throttle (default 8–16s between messages for same company). Email and System channels have no throttle. Failed jobs retry up to 3x with exponential backoff.
Policy resolution: Resolve in order: Plan feature flags → ClientCompanyNotificationOverride (per-client per-org) → ClientNotificationPreferences (client global) → CompanyNotificationPolicy (org default) → System defaults (all channels on).
Migration: No data migration needed — no pending notifications exist. New models are additive.
Affected Areas
| Area | Impact | Description |
|---|---|---|
notification-sender/src/ |
New | Complete rewrite: job polling, multi-channel dispatch, throttle |
server/src/Models/Notifications/ |
Modified | Add job creation service; existing adapters remain for direct sends |
server/src/Models/Appointments/Appointments.ts |
Modified | Replace inline sends with job creation calls |
server/src/Models/Plans/Plans.interface.ts |
Unchanged | Plan features already define channel support |
New: server/src/Models/NotificationJobs/ |
New | NotificationJob model + adapter |
New: server/src/Models/NotificationPolicies/ |
New | Company/Client policy models + resolution engine |
New: notification-sender/src/Models/Jobs/ |
New | Job polling model for worker |
Risks
| Risk | Likelihood | Mitigation |
|---|---|---|
| WhatsApp rate limit hit during high-volume periods | High | Per-company throttle (8–16s), exponential backoff on failures |
| Job queue grows faster than worker processes | Medium | Monitor queue depth; add alerting on backlog threshold |
| Policy resolution adds latency to appointment creation | Low | Resolution is a simple DB query cascade; cache per-request |
| Breaking existing notification behavior during transition | Medium | Feature flag: keep inline sends as fallback during rollout |
Rollback Plan
- Disable job creation in server via feature flag (reverts to inline sends)
- Stop notification-sender worker
- Existing inline notification paths remain unchanged — no code removal needed until stable
- Job collection can be truncated without data loss (jobs are ephemeral)
Dependencies
- MongoDB (shared across all modules) — already available
- Baileys (txbot) — existing WhatsApp integration, no changes needed
- DonWeb email API — existing integration, no changes needed
- Socket.IO — existing in server, no changes needed
Success Criteria
- Appointment creation/update/delete returns within normal latency (< 200ms)
- WhatsApp messages for same company spaced ≥ 8s apart
- Failed notifications retry up to 3x with exponential backoff
- Policy resolution correctly cascades through hierarchy
- Zero missed notifications during 24h soak test
- notification-sender processes backlog within 5 minutes under normal load