I am trying to roll out my own SMS verification system for my app. I don’t want to start paying for a service and then have them jack up the price on me (Urban Airship did that to me for push notification: lesson learned). During development and beta testing I have been using Twilio with a very basic setup: 1 phone number. It worked well for over a year, but right now for whatever reason the messages aren’t always delivered. In any case I need to create a better system for production. So I have the following specs in mind:
- 600 delivered SMS per minute
- zero misses
- save money
Right now my Twilio phone number can send one SMS per second; which means the best I can handle is 60 happy users per minute. So how do I get 600 happy users per minute?
So the obvious solution is to use 10 phone numbers. But how would I implement the system? My server is App Engine, DataStore, Java. So say I purchase 10 phone numbers from Twilio (fewer would of course be better). How do I implement the array so that it can handle concurrent calls from users? Will the following be sufficient?
public static final String[] phoneBank = {“1234567890”,”2345678901”,”3456789012”,”4567890123”,…};
public static volatile nextIndex;
public void sendSMSUsingTwilio(String message, String userPhone){
nextIndex = (nextIndex+1)%phoneBank.length;
String toPhone = phoneBank[nextIndex];
// boilerplate for sending sms with twilio goes here
//…
}
Now imagine 1000 users calling this function at the very same time. Would nextIndex run from 0,1,2…9,0,1…9,0,… successively until all requests are sent?
So really this is a concurrency problem. How will this concurrency issue work on Java AppEngine? Will there be interleaving? bottlenecking? I want this to be fast on a low budget: At least 600 per minute. So I definitely don’t want synchronization in the code itself to waste precious time. So how do I best synchronize calls to increment nextIndex
so that the phone numbers are each called equally and in a periodic fashion? Again, this is for Google App Engine.
You need to use Task API. Every message is a new task, and you can assign phone numbers using round-robin or random assignments. As a task is completed, App Engine will automatically pull and execute the next task. You can configure the desired throughput rate (for example, 10 per second), and App Engine will manage the required capacity for you.
You can try to implement something similar on your own, but it's much more difficult than you think - you have to handle concurrency, retries, instance shutdowns, memory limits, etc. Task API does all of that for you.