-
Notifications
You must be signed in to change notification settings - Fork 0
Home
NotifyEngine is an intelligent notification routing service that learns from user behavior to automatically choose the best delivery channel (email, SMS, WebSocket, or webhook) for every message. Designed for developers and product teams sending high‑volume notifications, it replaces static routing rules with an XGBoost ML model that adapts per‑user in real time.
Project Description as PDF | Download Project Description as DOCX
|
Henry Wong AI/ML Advisor |
||
Zeeya Ramani Data Analyst / Developer |
Salvatore Ardisi AI Engineer / Developer |
Rhythm Patel AI Engineer / Developer |
Dhawalshree Mengane Data Analyst / Developer |
Mohammed Nazir Yusif Security Engineer / Project Manager |
Krish Dhorajiya AI Engineer / Tester |
┌───────────────────┐
│ React Dashboard │
│ (Vite + Tailwind)│
└────────┬──────────┘
│ HTTP + WebSocket
▼
┌──────────┐ POST notifications ┌──────────────────┐ ┌──────────────┐
│ Developer│ ──────────────────────────► │ API Server │────►│ PostgreSQL │
│ Client │ ◄── 202 Accepted │ Express + TS │ │ (Multi-tenant│
└──────────┘ └────────┬─────────┘ │ + RLS) │
│ Enqueue └──────────────┘
▼ ▲
┌─────────────────┐ │
│ Redis + BullMQ │ │
│ (Job Queue) │ │
└────────┬────────┘ │
│ Dequeue │
▼ │
┌────────────────┐ │
│ Worker │──────────────┘
│ (Delivery + │
│ Feature Ext.) │
└───┬────────┬───┘
│ │
┌──────────────┘ └──────────────────┐
▼ ▼
┌───────────────────┐ ┌─────────────────────┐
│ ML Service │ │ Delivery Channels |
│ | | Email |
│ FastAPI + XGBoost│ │ SMS (mock) │
│ Epsilon-Greedy │ │ Websocket │
└───────────────────┘ │ Webhook │
└─────────────────────┘
| Component | Technology | Purpose |
|---|---|---|
| API Server | Node.js, Express, TypeScript | Request handling, auth, validation, enqueuing |
| Worker | Node.js, BullMQ, TypeScript | Feature extraction, ML routing, delivery execution |
| ML Service | Python, FastAPI, XGBoost | Engagement prediction, epsilon-greedy exploration |
| Database | PostgreSQL 16 | Multi-tenant storage with row-level security |
| Cache/Queue | Redis 7 + BullMQ | Async job processing, rate limiting, dashboard event pub/sub |
| Dashboard | React, Vite, Tailwind, shadcn/ui | Real-time analytics, routing intelligence, notification explorer |
| Real-time | Socket.IO | In-app delivery channel + live dashboard updates |
| Observability | Pino | Structured JSON logging |
| CI/CD | Docker, GitHub Actions | Containerized deployment, automated testing, secret scanning |
| Algorithm | Role | How It Works |
|---|---|---|
| XGBoost | Channel Prediction | Decision trees trained on delivery outcomes. Each tree corrects the previous tree's errors. Outputs per-channel engagement probability-highest wins. |
| Epsilon-Greedy | Exploration Strategy | Configurable per tenant (default 10% explore). Exploit uses model's best prediction, explore tries alternative channels. Prevents the model from getting stuck on old data. |
| Circuit Breaker | Reliability | Monitors provider failure rates in real-time. Opens on threshold -> reroutes to next-best channel -> auto-recovers utilizing a half-open test after cooldown. |
graph LR
CLIENT["Developer / Client App"]
DASHUSER["Dashboard User<br/>(Tenant Admin)"]
subgraph HOST["Host Machine - Node.js Services"]
direction TB
DASH["Dashboard<br/>React + Vite<br/>Port 5173"]
API["API Server<br/>Express + TypeScript<br/>Port 3000<br/>Socket.IO /dashboard"]
WORKER["Delivery Worker<br/>BullMQ + TypeScript<br/>4 Priority Queues<br/>Feature Extraction"]
end
subgraph DOCKER["Docker Compose - Infrastructure"]
direction TB
REDIS["Redis 7<br/>Port 6379<br/>BullMQ + Pub/Sub"]
PG["PostgreSQL 16<br/>Port 5432<br/>Multi-tenant RLS"]
ML["ML Service<br/>Python FastAPI<br/>Port 8000<br/>XGBoost"]
MAILPIT["Mailpit<br/>SMTP 1025<br/>UI 8025"]
end
CLIENT -->|"POST /v1/notifications"| API
CLIENT -->|"GET /v1/notifications/:id"| API
DASHUSER --> DASH
DASH -->|"REST API"| API
DASH -.->|"Socket.IO /dashboard"| API
API -->|"SHA-256 auth<br/>RLS context"| PG
API -->|"Enqueue jobs"| REDIS
API -.->|"SUBSCRIBE<br/>dashboard:events"| REDIS
WORKER -->|"Pick up jobs"| REDIS
WORKER -->|"Record attempts<br/>Update status"| PG
WORKER -->|"POST /predict"| ML
WORKER -->|"SMTP send"| MAILPIT
WORKER -.->|"PUBLISH<br/>dashboard:events"| REDIS
ML -->|"Training data<br/>Model metadata"| PG
style DOCKER fill:#1a1a2e,color:#e0e0e0
style HOST fill:#16213e,color:#e0e0e0
style CLIENT fill:#0f3460,color:#e0e0e0
style DASHUSER fill:#0f3460,color:#e0e0e0
| Service | Technology | Responsibility | Does NOT |
|---|---|---|---|
| API Server | Express + TypeScript | Auth, validation, rate limiting, enqueue, REST endpoints, Socket.IO dashboard events | Deliver notifications, call ML service, process BullMQ jobs |
| Worker | Node.js + BullMQ | Job processing, feature extraction, ML routing calls, delivery execution, outcome recording | Serve HTTP endpoints, train ML models |
| ML Service | Python + FastAPI | XGBoost prediction, model training, synthetic data generation | Serve notifications, connect to queue |
| Dashboard | React + Vite | Admin UI, real-time feed, routing intelligence visualization | Connect to DB directly, call ML service |
| PostgreSQL | PostgreSQL 16 | All persistent data with Row-Level Security per tenant | - |
| Redis | Redis 7 + BullMQ | Job queuing, rate limiting, usage counters, pub/sub events | - |
erDiagram
TENANTS ||--o{ API_KEYS : "authenticates via"
TENANTS ||--o{ CHANNELS : "delivers through"
TENANTS ||--o{ NOTIFICATIONS : "sends"
TENANTS ||--o{ RECIPIENT_CHANNEL_STATS : "tracks engagement for"
TENANTS ||--o{ MODEL_METADATA : "trains models for"
TENANTS ||--o{ USAGE_RECORDS : "meters usage for"
NOTIFICATIONS ||--o{ DELIVERY_ATTEMPTS : "attempted via"
CHANNELS ||--o{ DELIVERY_ATTEMPTS : "delivered through"
TENANTS {
uuid id PK
string name
string slug UK
string plan
boolean adaptive_routing_enabled
float exploration_rate
}
API_KEYS {
uuid id PK
uuid tenant_id FK
string key_hash UK
string key_prefix
string scopes
}
CHANNELS {
uuid id PK
uuid tenant_id FK
string type
string label
int priority
boolean is_enabled
string circuit_state
}
NOTIFICATIONS {
uuid id PK
uuid tenant_id FK
string recipient
string routing_mode
string priority
string status
jsonb routing_decision
}
DELIVERY_ATTEMPTS {
uuid id PK
uuid tenant_id FK
uuid notification_id FK
uuid channel_id FK
string status
boolean engaged
jsonb feature_vector
}
RECIPIENT_CHANNEL_STATS {
uuid id PK
uuid tenant_id FK
string recipient
string channel_type
int attempts_30d
int engagements_30d
}
MODEL_METADATA {
uuid id PK
uuid tenant_id FK
string version
float auc_roc
boolean is_active
jsonb feature_importance
}
USAGE_RECORDS {
uuid id PK
uuid tenant_id FK
date period_start
int notifications_sent
}
graph TB
DEV["Developer / Client Application<br/>(Tenant)"]
ADMIN["Dashboard User<br/>(Tenant Admin)"]
subgraph SYSTEM["NotifyEngine"]
CORE["Notification Delivery Service<br/>with ML-Powered Adaptive Routing"]
end
EMAIL_PROV["Email Provider<br/>(Mailpit / SES)"]
SMS_PROV["SMS Provider<br/>(Webhook-based)"]
RECIPIENT["Notification Recipient<br/>(End User)"]
DEV -->|"POST /v1/notifications<br/>API Key Authentication<br/>JSON payload"| SYSTEM
DEV -->|"GET /v1/notifications/:id<br/>Check delivery status"| SYSTEM
DEV -->|"POST /v1/tenants/register<br/>Create account + API key"| SYSTEM
ADMIN -->|"View dashboard<br/>Monitor notifications<br/>Check delivery stats"| SYSTEM
SYSTEM -->|"SMTP email delivery<br/>HTML + plain text"| EMAIL_PROV
SYSTEM -->|"HTTP POST webhook<br/>HMAC-signed payload"| SMS_PROV
SYSTEM -.->|"WebSocket push<br/>Socket.IO real-time"| RECIPIENT
EMAIL_PROV -->|"Email arrives<br/>in inbox"| RECIPIENT
SMS_PROV -->|"SMS delivered<br/>to phone"| RECIPIENT
RECIPIENT -.->|"Opens email<br/>(tracking pixel)"| SYSTEM
RECIPIENT -.->|"Acknowledges WebSocket<br/>(ws_ack event)"| SYSTEM
style SYSTEM fill:#1a1a2e,stroke:#334155,color:#e0e0e0
style DEV fill:#0f3460,stroke:#1e3a5f,color:#e0e0e0
style ADMIN fill:#0f3460,stroke:#1e3a5f,color:#e0e0e0
style EMAIL_PROV fill:#4a1d6a,stroke:#5b2d7a,color:#e0e0e0
style SMS_PROV fill:#4a1d6a,stroke:#5b2d7a,color:#e0e0e0
style RECIPIENT fill:#1b4332,stroke:#2d6a4f,color:#e0e0e0
style CORE fill:#16213e,stroke:#1e3a5f,color:#e0e0e0
sequenceDiagram
autonumber
participant Client as Developer
participant API as API Server
participant PG as PostgreSQL
participant Redis as Redis / BullMQ
participant Worker as Delivery Worker
participant Email as Mailpit (SMTP)
Note over Client,Email: Phase 1 - Send Notification
Client->>API: POST /v1/notifications<br/>Authorization: Bearer ne_test_...
API->>PG: SELECT from api_keys<br/>WHERE key_hash = SHA-256(token)
PG-->>API: tenant_id, scopes
API->>PG: SET tenant context (set_config)
API->>PG: Validate with Zod, then<br/>INSERT notification (status: pending)
PG-->>API: notification id
API->>Redis: Enqueue to notifications-{priority}
API->>PG: UPDATE status = 'queued'
API-->>Client: 202 Accepted<br/>{ id, status: queued, status_url }
Note over Client,Email: Phase 2 - Delivery
Redis->>Worker: Job picked up
Worker->>PG: SET tenant context (set_config)
Worker->>PG: UPDATE status = 'processing'
Worker->>PG: SELECT channels<br/>WHERE is_enabled<br/>ORDER BY priority DESC
Worker->>Worker: classifyContent (LLM)<br/>urgency, category, sentiment
Worker->>Worker: Filter channels via<br/>shouldAllowChannelProbe()
alt Static Routing
Note over Worker: Try channels in priority order
else Adaptive Routing
Worker->>Worker: Call ML Service /predict<br/>Epsilon-greedy channel selection
end
Worker->>Email: SMTP send to recipient
Email-->>Worker: 250 OK
Worker->>PG: INSERT delivery_attempt<br/>(status: success, duration_ms, tenant_id)
alt Recipient is simulation persona
Worker->>Worker: simulateEngagement (LLM)<br/>returns {engaged, reason}
Worker->>PG: UPDATE delivery_attempt<br/>engaged, engagement_reason
end
Worker->>PG: UPDATE notification<br/>status = delivered, delivered_via = email
Worker->>Redis: PUBLISH dashboard:events
Worker->>PG: RESET tenant context
Note over Client,Email: Phase 3 - Status Check
Client->>API: GET /v1/notifications/:id<br/>Authorization: Bearer ne_test_...
API->>PG: SELECT notification + delivery_attempts
PG-->>API: Full notification with attempts array
API-->>Client: 200 OK<br/>{ status: delivered, delivered_via: email,<br/>delivery_attempts: [...] }
Note over Client,Email: Phase 4 - Failure Path (if all channels fail)
Worker->>PG: UPDATE status = 'failed'
Note over Worker,Redis: BullMQ retries with exponential backoff
Worker->>Redis: After max retries: move to DLQ
Worker->>PG: UPDATE status = 'dlq'
flowchart LR
START(["Job arrives"]) --> STEP1
subgraph WORKER["Delivery Worker - per-job lifecycle"]
direction LR
STEP1["1 - Pick job<br/>from BullMQ"]
STEP2["2 - SET tenant context<br/>in Postgres"]
STEP3["3 - Query channels<br/>from Postgres"]
STEP4["4 - Extract features<br/>19 per channel"]
STEP5{"Routing mode?"}
STEP6A["6a - Static fallback<br/>priority order"]
STEP6B["6b - Call ML /predict<br/>epsilon-greedy"]
STEP7["7 - Deliver<br/>Email / SMS / WebSocket / Webhook"]
STEP8["8 - INSERT delivery_attempt<br/>with feature_vector"]
STEP9["9 - UPDATE notification status<br/>delivered / failed"]
STEP10["10 - PUBLISH dashboard:events<br/>to Redis"]
STEP11["11 - RESET tenant context<br/>release DB client"]
STEP1 --> STEP2 --> STEP3 --> STEP4 --> STEP5
STEP5 -->|Adaptive| STEP6B
STEP5 -->|Static| STEP6A
STEP6A --> STEP7
STEP6B --> STEP7
STEP7 --> STEP8 --> STEP9 --> STEP10 --> STEP11
end
STEP11 --> FINISH(["Job complete"])
style WORKER fill:#16213e,color:#e0e0e0
style START fill:#0f3460,color:#e0e0e0
style FINISH fill:#0f3460,color:#e0e0e0
style STEP5 fill:#4a3a1a,color:#e0e0e0
View User Manual as PDF | Download User Manual as Word Document
View Deployment Manual as PDF | Download Deployment Manual as Word Document
View Technical Paper as PDF | Download Technical Paper as Word Document
1a. Watch Sprint 0 Presentation Video | Click here to download mp4 File
1b. Sprint 0 Presentation Slides as PDF |
Sprint 0 Presentation Slides as PowerPoint
2a. Watch Sprint 1 Presentation Video | Click here to download mp4 File
2b. Sprint 1 Presentation Slides as PowerPoint |
Sprint 1 Presentation Slides as PDF
2c. Prototype
2d. Watch Sprint 1 Demo Video | Click here to download mp4 File
2e. View all Sprint 1 Source Code
3a.Watch Sprint 2 Presentation Video | Click here to download mp4 File
3b. Sprint 2 Presentation Slides as PowerPoint |
Sprint 2 Presentation Slides as PDF
3c. Watch Sprint 2 Demo Video | Click here to download mp4 File
3d. View all Sprint 2 Source Code
4a.Watch Sprint 3 Presentation Video | Click here to download mp4 File
4b. View Sprint 3 Presentation Slides as PDF
4b. Download Sprint 3 Presentation Slides as PowerPoint
4c. Watch Sprint 3 Demo Video | Click here to download mp4 File
4d. View all Sprint 3 Source Code
- Sprint 0 Completed Tasks
- Sprint 1 Burndown Chart and Completed Tasks
- Sprint 2 Burndown Chart and Completed Tasks
- Sprint 3 Burndown Chart and Completed Tasks
- Watch Sprint 1 Planning Recording
- Watch Sprint 2 Planning Recording
- Watch Sprint 3 Planning Recording [Click here to download mp4 File] (https://github.com/htmw/2026S-Algo-Rhythms/raw/develop/Documents/Sprint-3/Sprint%203%20Planning.mp4)
- Watch Sprint 0 Retrospective Video | Click here to download mp4 File
- Watch Sprint 1 Retrospective Video | Click here to download mp4 File
- Watch Sprint 2 Retrospective Video | Click here to download mp4 File
- Watch Sprint 3 Retrospective Video | Click here to download mp4 File
Team Working Agreement as PDF | Download Team Working Agreement as DOCX
![]() |
![]() |
![]() |
| Sarah Kim | Daniel Ross | Amanda Lopez |
| Backend Developer Persona PDF | Product Manager Persona PDF | Growth Lead Persona PDF |
- View Sprint 1 User Stories w/ Acceptance Criteria as PDF
- Download Sprint 1 User Stories w/ Acceptance Criteria as Excel Workbook
- View Sprint 2 User Stories w/ Acceptance Criteria as PDF
- Download Sprint 2 User Stories w/ Acceptance Criteria as Excel Workbook
- View Sprint 3 User Stories w/ Acceptance Criteria as PDF
- Download Sprint 3 User Stories w/ Acceptance Criteria as Excel Workbook
- View Sprint 1 Test Cases Spreadsheet as PDF
- View Sprint 1 Test Cases Spreadsheet as Excel Workbook
- View Sprint 2 Test Cases Spreadsheet as PDF
- View Sprint 2 Test Cases Spreadsheet as Excel Workbook
- View Sprint 3 Test Cases Spreadsheet as PDF
- View Sprint 3 Test Cases Spreadsheet as Excel Workbook
notifyengine/
├── apps/
│ ├── api/ # Node.js Express API server (TypeScript)
│ ├── worker/ # BullMQ queue workers (TypeScript)
│ ├── ml-service/ # Python FastAPI ML prediction + training
│ └── dashboard/ # React admin dashboard (Vite + Tailwind)
├── packages/
│ └── shared/ # Shared TypeScript types + constants
├── infra/
│ ├── migrations/ # PostgreSQL migrations (numbered, sequential)
│ ├── seed/ # Database seed scripts
│ └── migrate.ts # Migration runner
├── scripts/ # Dev setup and utility scripts
├── .github/workflows/ # CI/CD + TruffleHog secret scanning
├── docker-compose.yml # Dev infrastructure (Postgres, Redis, Mailpit, ML)
├── turbo.json # Turborepo pipeline config
├── .env.example # Environment variable template
├── package.json # Root workspace config
├── README.md
└── CLAUDE.md # Project config with coding standards + security rules


