Junada WhatsApp Suite
WhatsApp broadcast and template automation for a regional e-commerce operator. Direct Meta Cloud API integration, 1.2M messages routed monthly at 99.9% deliverability.
About the project.
Junada is a WhatsApp broadcast and template automation suite I built for a regional e-commerce operator who was bleeding money on per-message platform fees. The system talks to the Meta Cloud API directly, manages template approval, and routes large broadcasts through a queue that respects per-customer rate limits. I designed and built the backend, the queue layer, and the admin tooling. It moves over a million messages a month without a third-party intermediary.
What changed.
messages routed per month
deliverability
API latency, p95
What we walked into.
An e-commerce operator wanted to broadcast order updates and promotional messages to their customer base via WhatsApp without paying per-message platform fees forever.
What we did.
Direct integration with the Meta Cloud API, a Node.js queue that respects per-customer rate limits, and a template-management UI that mirrors WhatsApp's own approval flow so admins know upfront whether a draft will be accepted.
What it became.
Routing 1.2 million messages per month at 99.9% deliverability with sub-300ms median dispatch latency.
My role on this project.
Solo · 100% backend + queue + admin UI + Meta API integration. No SaaS layer (Twilio, MessageBird, 360dialog) sitting between the operator and Meta. Direct relationship with Meta Cloud API means margin retained, full template control, and no per-message middleman fees.
Backend engineer
Node.js 20 + Fastify. Direct Meta Cloud API client, webhook handler for delivery receipts, template-status sync.
Queue + rate-limit engineer
BullMQ on Redis. Per-customer rate-limit buckets respecting WhatsApp's tier system (250/1k/10k/100k msg/day depending on quality score).
Admin UI engineer
Template builder mirroring Meta's approval form, broadcast scheduler, recipient list manager, delivery-rate dashboard with real-time updates.
DevOps + observability
PM2, MongoDB Atlas, Sentry for error tracking, Grafana dashboards for delivery rate + queue depth.
The numbers that matter.
- 1.2M+Messages routed monthlySteady-state production volume; spikes during sale events.
- 99.9%DeliverabilityMeta-confirmed delivered (not just dispatched). Failed sends auto-quarantined + retried after analysis.
- <300msMedian dispatch latencyEnqueue → Meta API ack, measured at the broadcast worker.
- $0Per-message middleware feeDirect Meta integration — only Meta's conversation pricing applies. No SaaS markup.
- ~85%Template approval rateEstimated — admin UI catches the most common rejection causes before submission to Meta.
- <2sWebhook delivery-receipt processingMeta webhook → DB update → dashboard refresh.
What was actually broken.
WhatsApp messaging at scale forces a choice: pay Twilio/MessageBird/360dialog roughly $0.005-0.015 per message in middleware fees on top of Meta's conversation pricing — at 1M messages/month that is $5k-$15k/month going to a middleman that adds queue management + dashboards but holds your business hostage to their pricing. Or integrate Meta Cloud API directly, which means building the queue, the template-approval lifecycle, the delivery-receipt webhook handling, the rate-limit-tier compliance, and the dashboards yourself. The operator chose direct integration after running the math past Year 1.
The hard surface area.
- 01WhatsApp rate-limit tier system (250 → 1k → 10k → 100k → unlimited messages/day depending on quality score) requires per-customer token bucket that respects the current tier AND auto-throttles when quality score dips.
- 02Template approval lifecycle: drafts → submitted → in_review → approved/rejected. Admin UI must mirror Meta's rejection reasons exactly so operators iterate fast without submitting bad drafts.
- 03Delivery receipts arrive async via webhooks for each message — at 40k messages/day that is 40k webhook hits. Must process all of them within 2 seconds to keep the dashboard live.
- 04Recipient list management: WhatsApp requires opt-in confirmation per phone number; the platform must track consent status + per-phone delivery history to avoid silent quality-score damage from sending to unresponsive numbers.
- 05Cost transparency: operators want per-broadcast cost in their currency BEFORE pressing send. Meta's pricing varies by recipient country + conversation category (utility, marketing, authentication, service). Calculator must match Meta's billing within ±2%.
Engineering wins worth naming.
Per-customer rate-limit bucket
Token bucket per WhatsApp Business Account (WABA), refilled at the rate matching the current tier. When tier downgrades (quality score drop), bucket immediately resets to new limit. No queue overflow.
Template approval-aware admin UI
Admin UI runs Meta's rejection-reason regex set CLIENT-SIDE before submit. Operators see warnings (e.g. "Marketing templates cannot contain phone numbers in the body") and edit before burning a submission slot.
Webhook idempotency
Meta retries failed webhook deliveries up to 24h. Same delivery receipt may arrive 5+ times. Idempotency key on (waba_id + message_id + status) prevents double-counting.
Cost-prediction engine
Pre-fetched Meta pricing matrix, refreshed daily. Per-recipient country lookup, conversation-category classification, currency conversion against operator base currency. ±2% accuracy verified against monthly Meta invoices.
How the system is wired.
Edge tier
Application tier (Node.js)
Async + queue tier
Data tier
The decisions behind each choice.
Node.js + Fastify (backend)
- Event-driven runtime is the natural fit for high-throughput webhook + queue I/O — 40k receipts/day with single-digit CPU.
- Fastify outperforms Express by 2-3x on JSON throughput at the small request sizes WhatsApp webhooks produce.
- Native async/await + Promise.all patterns make per-broadcast fan-out trivial.
BullMQ + Redis (queue)
- Per-WABA queue names give natural per-customer isolation without separate Redis instances.
- Built-in retry-with-backoff handles Meta's 429s without custom code.
- Job priorities let urgent transactional messages cut in line ahead of bulk marketing broadcasts.
MongoDB (templates + broadcasts)
- Templates have wildly varying structure (header media types, button counts, language overrides) — JSON-native storage avoids 5+ migrations per template feature.
- Aggregation pipelines power the delivery-rate dashboard without an OLAP sidecar.
Direct Meta Cloud API (no middleware SaaS)
- At 1M+ messages/month, middleware fees ($5k-$15k/month) exceed the cost of building the broker once.
- Full control over template lifecycle, tier upgrades, and quality-score recovery — no SaaS layer hiding the levers.
- Direct WABA ownership stays with the operator; switching providers later means swapping queue + dashboard, not migrating account state.
What the build taught us.
- Per-message middleware fees compound. At any meaningful volume, owning the broker pays for itself within a year.
- WhatsApp's rate-limit tier system rewards good actors — but it punishes mistakes hard. Quality-score recovery takes weeks. Build the admin UI to prevent bad drafts before they ship, not just to react to rejections.
- Webhook idempotency is not optional. Meta WILL retry. Plan for it from day one.
