The Brief
In 2009, ahead of the Andhra Pradesh state elections, the Telugu Desam Party (TDP) approached Airhub with a campaign requirement: reach their entire voter base of approximately 4 crore (40 million) people via SMS. Not once — multiple times throughout the campaign period. With personalised messages where possible.
At the time, this was one of the largest SMS campaigns attempted in India. Here's how we delivered it.
The Scale Challenge
40 million messages, even at 200K TPS, takes roughly 200 seconds per campaign send — just over 3 minutes. But the reality was more complex:
- ·Operator spread: Those 40 million numbers were spread across Vodafone, Airtel, Idea, BSNL, Tata Docomo, and several smaller operators. Each had different SMPP capacity limits and throughput agreements.
- ·DND compliance: India's Do Not Disturb registry had to be scrubbed against the recipient list before each send.
- ·Delivery receipts: Political campaigns care deeply about delivery rates. We had to track delivery receipts back from every operator — at 40M messages per send, that's 40M callbacks to process.
- ·Message personalisation: Where voter data included names, messages could be personalised ("Dear [Name], TDP invites you to..."). Variable-length messages complicated our batching strategy.
The Infrastructure
We ran our Kannel cluster across multiple servers, each maintaining SMPP connections to operator SMSCs. The architecture:
[Campaign API] → [Message Queue] → [Kannel Cluster] → [Operator SMSCs]
↓
[Delivery Receipt Processor]
↓
[Analytics Database]The message queue was essential — it decoupled the rate of message generation (which could burst) from the rate of delivery (which was throttled by operator limits). We used a simple MySQL-backed queue with locking; today I'd use something like SQS or RabbitMQ.
The delivery receipt processor was a significant engineering challenge. Operators send receipts asynchronously, sometimes hours after the original message. Correlating receipts back to original messages required careful state management.
What Nearly Broke Us
Phone number validity: India had undergone MNP (Mobile Number Portability), meaning the prefix no longer reliably indicated the operator. Our initial routing logic assumed prefix-to-operator mapping — we had to rebuild it based on a regularly updated number portability database.
Operator throttling: During peak campaign periods, multiple campaigns were running simultaneously across all operators. Operators would throttle connections without warning. We needed dynamic throttle detection and automatic backoff.
Memory pressure: At peak, we had millions of unacknowledged messages in various states (sent, delivered, failed, pending). The state management memory footprint was larger than we'd planned.
The Result
Over the campaign period, we sent approximately 4 crore messages per major campaign send, with multiple sends across the campaign duration. Delivery rates above 85% (the remainder being invalid numbers or DND registrations).
The experience gave me a deep respect for distributed systems problems that look simple on the surface. "Send an SMS to everyone in this list" hides an enormous amount of operational complexity.