-
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, push, or in‑app) 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.
Unlike developer tools like Courier, Knock, or Novu that rely on fixed priority rules, and enterprise platforms like Braze or MoEngage that cost $50K+/year and aren't developer-first, NotifyEngine offers a simple API with per‑user ML routing that continuously improves with every notification sent.
Key outcomes: Higher engagement rates, lower SMS spending, circuit breaker during provider outages, and no manual routing logic to maintain.
Project Description as PDF | Download Project Description as DOCX
![]() 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 │
│ FastAPI + XGBoost│ │ Email │
│ Epsilon-Greedy │ │ Push │
└───────────────────┘ │ SMS │
│ In-App │
└─────────────────────┘
| 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 + BullMQ | Async job processing, rate limiting, caching |
| 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 | Prometheus, Grafana, Pino | Metrics, dashboards, 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 | 90% exploit (use model's best prediction), 10% explore (try 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 TB
subgraph Clients["CLIENTS / TENANTS"]
APP1["App 1<br/>REST API Client"]
APP2["App 2<br/>REST API Client"]
APP3["App N<br/>REST API Client"]
end
subgraph API["API SERVER (Express + TypeScript)"]
AUTH["API Key Auth<br/>SHA-256 Lookup"]
VALID["Zod Validation<br/>Middleware"]
RATE["Rate Limiter<br/>Token Bucket"]
ROUTES["REST Endpoints<br/>/v1/notifications<br/>/v1/tenants<br/>/v1/channels"]
SOCKETIO["Socket.IO Server<br/>Dashboard Events"]
end
subgraph Queue["MESSAGE QUEUE (Redis + BullMQ)"]
CRIT["notifications:critical<br/>concurrency: 20"]
HIGH["notifications:high<br/>concurrency: 10"]
STD["notifications:standard<br/>concurrency: 5"]
BULK["notifications:bulk<br/>concurrency: 2"]
DLQ["notifications:dlq<br/>manual review"]
RETRAIN["ml:retrain<br/>periodic"]
ROLLUP["stats:rollup<br/>periodic"]
end
subgraph Worker["DELIVERY WORKER (Node.js + TypeScript)"]
JOBPICK["Job Processor<br/>BullMQ Worker"]
FEAT["Feature Extractor<br/>15-Feature Vector"]
ROUTER["Channel Router<br/>Static / Adaptive / Forced"]
CB["Circuit Breaker<br/>Per-Channel State"]
EMAIL["Email Delivery<br/>Nodemailer / Mailtrap"]
SMS["SMS Webhook<br/>Mock Provider"]
WS["WebSocket Delivery<br/>Socket.IO"]
WEBHOOK["Generic Webhook<br/>HMAC Signed"]
end
subgraph ML["ML SERVICE (Python + FastAPI)"]
PREDICT["POST /predict<br/>XGBoost Inference"]
TRAIN["POST /train<br/>Model Retraining"]
SYNTH["Synthetic Data<br/>Generator"]
MODEL["XGBoost Model<br/>.joblib Artifact"]
end
subgraph DB["POSTGRESQL 16"]
TENANTS["tenants"]
APIKEYS["api_keys<br/>SHA-256 Hashed"]
CHANNELS["channels<br/>Circuit Breaker State"]
NOTIF["notifications<br/>routing_decision JSONB"]
DELIVERY["delivery_attempts<br/>feature_vector JSONB"]
STATS["recipient_channel_stats<br/>Aggregated Metrics"]
MODELMETA["model_metadata<br/>Accuracy + Importance"]
USAGE["usage_records<br/>Per-Tenant Metering"]
RLS["Row-Level Security<br/>app.current_tenant_id"]
end
subgraph Dashboard["DASHBOARD (React + Vite + TypeScript)"]
DASH_UI["Admin Dashboard<br/>TanStack Query"]
REALTIME["Real-Time Feed<br/>Socket.IO Client"]
ROUTING_INT["Routing Intelligence<br/>Feature Importance"]
end
subgraph Observability["OBSERVABILITY"]
PROM["Prometheus<br/>Metrics Collection"]
GRAF["Grafana<br/>Dashboards"]
PINO["Pino<br/>Structured JSON Logs"]
end
APP1 -->|"HTTPS + API Key"| AUTH
APP2 -->|"HTTPS + API Key"| AUTH
APP3 -->|"HTTPS + API Key"| AUTH
AUTH --> VALID
VALID --> RATE
RATE --> ROUTES
ROUTES -->|"Enqueue Job<br/>Return 202"| Queue
ROUTES -->|"Read/Write"| DB
API -->|"Pub/Sub Subscribe<br/>dashboard:events"| Queue
SOCKETIO -->|"Broadcast Events"| Dashboard
CRIT --> JOBPICK
HIGH --> JOBPICK
STD --> JOBPICK
BULK --> JOBPICK
JOBPICK --> FEAT
FEAT -->|"Query Stats"| DB
FEAT --> ROUTER
ROUTER -->|"POST /predict"| PREDICT
PREDICT --> MODEL
ROUTER --> CB
CB --> EMAIL
CB --> SMS
CB --> WS
CB --> WEBHOOK
EMAIL -->|"Record Attempt"| DB
SMS -->|"Record Attempt"| DB
WS -->|"Record Attempt"| DB
WEBHOOK -->|"Record Attempt"| DB
Worker -->|"Publish Events"| Queue
TRAIN -->|"Read Training Data"| DB
TRAIN --> MODEL
TRAIN -->|"Store Metadata"| DB
RETRAIN -->|"Trigger"| TRAIN
ROLLUP -->|"Aggregate Stats"| DB
DASH_UI -->|"REST API Only"| ROUTES
REALTIME -->|"Socket.IO"| SOCKETIO
Worker --> PINO
API --> PINO
ML --> PINO
PROM -->|"Scrape Metrics"| API
PROM -->|"Scrape Metrics"| Worker
PROM -->|"Scrape Metrics"| ML
PROM --> GRAF
classDef apiStyle fill:#2563eb,stroke:#1d4ed8,color:#fff
classDef workerStyle fill:#7c3aed,stroke:#6d28d9,color:#fff
classDef mlStyle fill:#059669,stroke:#047857,color:#fff
classDef dbStyle fill:#dc2626,stroke:#b91c1c,color:#fff
classDef queueStyle fill:#d97706,stroke:#b45309,color:#fff
classDef dashStyle fill:#0891b2,stroke:#0e7490,color:#fff
classDef obsStyle fill:#4b5563,stroke:#374151,color:#fff
class AUTH,VALID,RATE,ROUTES,SOCKETIO apiStyle
class JOBPICK,FEAT,ROUTER,CB,EMAIL,SMS,WS,WEBHOOK workerStyle
class PREDICT,TRAIN,SYNTH,MODEL mlStyle
class TENANTS,APIKEYS,CHANNELS,NOTIF,DELIVERY,STATS,MODELMETA,USAGE,RLS dbStyle
class CRIT,HIGH,STD,BULK,DLQ,RETRAIN,ROLLUP queueStyle
class DASH_UI,REALTIME,ROUTING_INT dashStyle
class PROM,GRAF,PINO obsStyle
| 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 | - |
-
Watch Sprint 0 Presentation Video | Click here to download mp4 File
0a. View Sprint 0 Presentation Slides as PDF
0b. Download Sprint 0 Presentation Slides as PowerPoint
-
Watch Sprint 1 Presentation Video | Click here to download mp4 File
1a. View Sprint 1 Presentation Slides as PDF
1b. Download Sprint 1 Presentation Slides as PowerPoint
1c. Prototype
1d. Watch Sprint 1 Demo Video | Click here to download mp4 File
1e. Sprint 1 Source Code
- Watch Sprint 0 Retrospective Video | Click here to download mp4 File
- Watch Sprint 1 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 |
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/
│ ├── docker-compose.yml
│ ├── prometheus.yml
│ ├── grafana/dashboards/
│ └── migrations/ # PostgreSQL migrations
├── models/ # XGBoost model artifacts
├── .github/workflows/ # CI/CD + TruffleHog secret scanning
├── turbo.json
├── package.json
└── CLAUDE.md # Project config with coding standards + security rules








