Implementing a simple serverless SMS handler with Twilio and AWS Lambda


In some projects you need a way to receive and handle SMS messages. Your project might require you to make custom actions based on content of a received SMS or send SMS from your application. Ideally you would want the integration of SMS functionality to be easy and affordable. Your country probably has some local actors that provide SMS services but these might not be the best options if you want to get up and running fast and affordably.

Amazon’s Simple Notification Service (SNS) would be a natural choice when working with Amazon’s cloud services. With SNS you can send SMS, Mobile Push notifications, Email and more. But with SNS you can’t receive SMS from users and this gap must be filled somehow.

Twilio can be the answer if you need a way to handle incoming and outgoing SMS, voice, or even fax. You can send and receive SMS on a local or global scale. Twilio provides a broad set of easy to use tools, pay-per-use pricing and scalability.

In this post we will talk about my experience using Twilio for a simple serverless SMS handler. We will also discuss things that you should know before deciding to use Twilio for a project.

What is Twilio?

Twilio is a cloud service for phone calls, SMS, video and a lot more. Twilio provides rich APIs, open source libraries and SDKs for different programming languages which make using the service nice and easy. Twilio even provides a visual editor for building Twilio apps and a serverless hosting service for your Twilio code.

Twilio is a fully scalable cloud service with a pay-per-use pricing model. Twilio also deserves praise for their somewhat intuitive and fancy dashboard.

Competitors to Twilio

There are a couple of services similar to Twilio on the market. Two services worth mentioning are Nexmo and Plivo. The availability of services, phone number availability in countries and pricing varies between these providers. The comparison of these services is outside scope of this post but before choosing a service be sure to investigate and compare which one is the best option for you. In this post we are solely focusing on Twilio.

Things to know when considering using Twilio

Firstly you should check from your Twilio dashboard that your country is supported for the service you want to use. For example Twilio doesn’t yet provide finnish SMS compatible numbers but in our case we were fine with using an Estonian number for the simple serverless SMS handler.

Of course pricing is important and something you might have to think about. Pricing varies by country. With Twilio you only pay for what you use. As with any pay-per-use cloud service you really do pay for everything you use so make sure that you are aware of the volume you are going to need to avoid being blown away by massive bills. This should not be a problem unless you operate on a massive scale.

In the case of SMS numbers you pay for sending and receiving SMS. The price of sending and receiving SMS can vary by carrier. You also pay a fixed rate per month for each number you have bought from Twilio. At least this is the case with Estonian SMS numbers. Check the pricing for your country before using the service.

Twilio works in the way that it charges you a fixed amount (20$ – 2000$ in 10$ increments, 14.7.2018) when your funds drop under a specified amount (10$ – 1000$ in 10$ increments, 14.7.2018). You can also manually add funds to your account.

Finally, as with any service you are about to use, make sure you understand the acceptable use policy. Twilio has a minimum usage requirement of two (2) transmissions for each SMS number per month. If your SMS number is deemed inactive it might be released for others to buy. This is understandable since there exists a finite amount of phone numbers.

Case: simple serverless SMS handler

In this example we simply want to receive SMS, handle them and respond with an SMS.

The high level architecture for this handler is seen in figure 1.

Figure 1

The process begins with a user sending an SMS to the number you have bought from Twilio. Twilio receives the SMS and does a HTTP POST request to the URL you have defined in the Twilio dashboard. You can choose if you want the request to be either GET or POST.

In this case the URL is an API Gateway endpoint that triggers a Lambda Node.js function. The function will handle the message however you decide to and in our case it posts a message to one of our company’s chat rooms.

The function uses Twilio’s Node.js SDK to answer the SMS with an SMS.

The lambda function

The function is Node.js and uses Express. Naturally, to use the Twilio SDK we have to add the library to our dependencies. In order for the SDK to work you must define two (2) global variables TWILIO_SID and TWILIO_AUTH_TOKEN. You can get both of these from your Twilio dashboard. If you for some reason don’t have these global variables set, you can also start using the SDK in the way shown in the below code snippet.

const accountSid = ‘yourAccountSid’

const authToken = ‘your_auth_token’

const twilio = require(‘twilio’)(accountSid, authToken)

Request validation

Twilio is nice enough to provide a webhook that can validate that the request really is from Twilio. In the code snippet below the middleware takes the parameters validate and url. No parameters are required by the middleware.

validate (true/false): If the request should be validated or not. It is configured to be false in local development and true in test and production.

url (string): In our case this parameter must be given because the SSL connection is terminated upstream in our stack and the URL our function receives does not match the URL Twilio calls to reach our application. Therefore to successfully validate the request we must set the url parameter. The url parameter is the same url that you have defined in the Twilio dashboard for the HTTP POST request.

const twilio = require(‘twilio’),

config = require(‘../lib/config’)

// Twilio webhook handles validation of request

router.post(‘/api/your-api’, twilio.webhook({validate: config.validateTwilioRequest, url: config.twilioWebhookCallback}), (req, res, next) => {

// Handle request


Handling and answering a request

Incoming SMS have a bunch of properties. In this case we are interested in the content of the SMS and the sender’s phone number. They are naturally found from the request body as seen in the code snippet below.

const twilio = require(‘twilio’),

config = require(‘../lib/config’),

MessagingResponse = require(‘twilio’).twiml.MessagingResponse

// Twilio webhook handles validation of request

router.post(‘/api/your-api’, twilio.webhook({validate: config.validateTwilioRequest, url: config.twilioWebhookCallback}), (req, res, next) => {

// SMS content

const receivedMessage = req.body.Body

// Sender of the SMS

cont senderPhoneNumber = req.body.From

// Handle the SMS how you want

// E.g. send the content to company chat

// Create response SMS

const twilioResponse = new MessagingResponse()

twilioResponse.message(‘Thank you. Message received :)’)

// Respond

res.writeHead(200, {‘Content-Type’: ‘text/xml’})



Under the hood Twilio uses Twilio Markup Language (TwiML, basically XML-documents) as the data format between transmissions which you don’t luckily have to code yourself (unless you want to).


Twilio is a good choice for applications that need to receive and send SMS especially because of its easy signup, fancy dashboard, developer friendly APIs and SDKs, exhaustive documentation, scalability and affordable pricing.

As a service Twilio is interesting and it opens up opportunities for you because it makes powerful SMS and other services accessible to everyone. It is easy to use it in conjunction with other cloud services, like AWS Lambda.

On a final note when using Twilio you might have to pay close attention to your spending. Also be sure to check the availability of services you want to use in your country.

Kim Martesuo
Kim Martesuo