A fix to one bug that Twilio doesn’t want you to know about

Lior Messinger
3 min readFeb 9, 2019

--

Short Message Service is one of the best channels to get a message across. Everyone with a smartphone can send and receive messages, regardless of the instant messenger they use. It can contain images and links, and you can send it as a push notification without much hassle.

Several companies offer easy to handle API to allow programmatic SMS handling. Some are less known and localized to their own country, but clearly the international leader is Twilio, which offers developers many ways to integrate messaging, voice, and even emails — starting from RESTful API and ending in Autopilot visual flow editor. It seems that a developer can easily build a chat bot, for example, that communicates over text messages.

Or can she? Well, not many developers know, but Twilio does not guarantee the order of its messages! This means, that if you’d like to send your customers a reminder that is split across several sentences, you might be heading for trouble. For example, what would be more natural than sending the following 4 messages:

Hi!
It seems you haven't activated your account.
The faster you activate it, the more you save!
Would you like me to help you activate it?

But as it turns out, these could appear on the customer’s phone as:

The faster you activate it, the more you save!
Would you like me to help you activate it?
It seems you haven't activated your account.
Hi!

How embarrassing is that?

The problem is, that due to carriers ancient infrastructure, one cannot guarantee the order upon arrival, as Twilio itself admits.

Fortunately, there are some ways around it. We came across the problem when developing a channel driver for Twilio in Servo’s conversational framework. Unfortunately, this discovery was made just one hour before an important demo to a client, so we couldn’t fix it right away and had to pray to the demo gods. But right after the meeting we started hacking away on the keyboard, trying a few options.

Most natural method that came to mind was to allow some time between the messages. It has the drawback that it would slow the conversation, but the hope was that 500ms delay wouldn’t be too bad. However, this didn’t work well enough.

The next evolution step was simple enough, and that one worked. We simply waited until Twilio drivers acknowledged that the message was received — by sending back the response — and then wait 500ms, or what was left of it. As always, it’s better to use decoupled queues to implement it. I’ll give you the essence here, and if you need the rest of the details, check the code itself in Github — under the server/chat folder.

When a message arrive the channel driver for sending, we put it into a messages queue.

...
_clients[process.fsm_id].messages.push(msg);
...

And once for every conversation, we call a recurrent function that would extract this message from the queue:

if (!_clients[process.fsm_id].messages.length) {this.send1Message(msg, process);} 

which would call

function send1Message(msg, process) { twilio.sendMessage(msg, (err, responseData) => {    if (!err) {          setTimeout(() => {            msg = _clients[process.fsm_id].messages.pop();            this.send1Message(msg, process);// <== recursive loop          }, this.timeoutMs);   } else {      console.error('twilio message err', err.message + ' ' +   err.moreInfo, msg);   } });}

that’s it! it worked.

And what about that demo? Well, after all, the demo did go well. Unexpectedly, and against all our usual bad luck, demo gods was on our side that day.

--

--

Lior Messinger

A software poet. A game warrior. A biological computer. Trying to make software soft again.