SIGNAL, our customer and developer conference, was only a few days ago. In case you missed it, you can have a look at the keynotes from day one and day two and also many of the product sessions on YouTube.
Twilio Functions now can be deployed via API and this changes how many people will develop with Twilio.
Developing in a serverless environment can be challenging and raise many questions. How do you develop your serverless project locally? How do you deploy your functions to production? How do you structure your code in the first place?
Luckily, two product announcements answer all of these questions. In this article, I want to share how the new Serverless Toolkit and the new Twilio Runtime API will change the creation, development, and deployment flow of Twilio functions.
Before we get started…
To develop and deploy Twilio functions you need:
You can use the Serverless Toolkit as a standalone tool in the form of the npm package twilio-run, however, you can also integrate it into the Twilio CLI via the Twilio Serverless plugin. The Twilio CLI covers hundreds of Twilio features and API endpoints, pair it with the Serverless plugin and you have a tool that provides all the functionality you need.
After installing the CLI, you have the
twilio command available in your environment. Ensure that you are authorized by running the following command in your terminal:
If you need more info on how to get started with the Twilio CLI check out the Twilio video tip “Introducing the Twilio CLI!”.
After a fresh installation, the Twilio CLI is missing the
serverless commands. To add these commands, install the serverless plugin from within the Twilio CLI itself. Run the
twilio plugins:install @twilio-labs/plugin-serverless
After the plugin installation finishes, new commands like
twilio serverless:deploy and
twilio serverless:start become available right at your fingertips. 🎉
A quick note about plugin; the Twilio CLI is not only able to install plugins but it also provides the functionality to keep plugins up-to-date. The serverless plugin is still pretty new – make sure to run
twilio plugins:update now and then to receive updates.
Create a new Serverless project
To get started with a new Twilio Runtime project, it only takes one command.
twilio serverless:init your-project-name
twilio serverless:init creates a new directory and mandatory files. It also installs all the required dependencies in one go.
twilio serverless:init serverless-tryout ✔ Creating project directory ✔ Creating project directories and files ✔ Downloading .gitignore file ✔ Installing dependencies ╭─────────────────────────────────────────────────────────────────────────────╮ │ │ │ Success! │ │ │ │ Created serverless-tryout at /your/dir │ │ │ │ Inside that directory, you can run the following command: │ │ │ │ npm start │ │ Serves all functions in the ./functions subdirectory and assets in the │ │ ./assets directory │ │ │ │ Get started by running: │ │ │ │ cd your-project-name │ │ npm start │ │ │ ╰─────────────────────────────────────────────────────────────────────────────╯
Navigate into the new directory and have a look at the included files. It should look similar to the tree below.
. ├── assets │ ├── index.html │ ├── message.private.js │ └── style.css ├── functions │ ├── hello-world.js │ ├── private-message.js │ ├── sms │ └ └── reply.protected.js ├── node_modules │ ├──... │ ├──... │ └──... ├── .env ├── .gitignore ├── .nvmrc ├── package-lock.json └── package.json
The new project includes config files and two main directories:
./functions/hello-world.js will be available at
The filename rules them all – public vs. private vs. protected access
Some of the generated functions and assets include a
private keyword in their filename. The Serverless Toolkit evaluates access permissions using the filename and omits the keywords in the public URL after the deployment. The file
/functions/sms/reply.protected.js will result in a
The access levels for functions are:
public(default) – publicly available
protected– only accessible by Twilio via, for examples, webhooks
And access levels for assets are:
public- publicly available
private- only accessible inside of functions via
Let’s sum up the new project, it includes:
- three assets (one of them is
privateand won’t be accessible publicly)
- three functions (one of them is
protectedand won’t be accessible publicly)
Now it’s time to see what all of them do and run the project locally!
A fresh Twilio Runtime right on your computer
Developing local serverless projects was always a pain. Luckily, there is now a command that emulates the Twilio Runtime on your machine and makes development much more convenient.
twilio serverless:start inside of the project.
twilio serverless:start ┌────────────────────────────────────────────────────────────────────┐ │ │ │ Twilio functions available: │ │ ├── /hello-world | http://localhost:3000/hello-world │ │ ├── /private-message | http://localhost:3000/private-message │ │ └── [protected] /sms/reply | http://localhost:3000/sms/reply │ │ │ │ Twilio assets available: │ │ ├── /index.html | http://localhost:3000/index.html │ │ ├── /style.css | http://localhost:3000/style.css │ │ └── [private] /message.js | Runtime.getAssets()['/message.js'] │ │ │ └────────────────────────────────────────────────────────────────────┘
twilio serverless:start command spins up a local server, creates the endpoints that would be deployed on the Runtime, and also emulates the environment by providing things like the
Runtime client. Your
localhost will behave like Twilio’s infrastructure! 🎉
When you visit the local endpoints, you’ll find out that all the functions respond with some TwiML covering everyday use cases like responding text to an incoming SMS. You can now take these functions and tweak them to your needs.
For further instructions and explanations, navigate to the included asset
http://localhost:3000/index.html. The example HTML page gives you more insights into the functions, assets, and the foundation for the serverless plugin – the underlying tool; twilio-run.
One last thing to mention about local development –
twilio serverless:start offers many flags that will help you with environment variables, debugging and live-reloading. It even comes with the local tunnel tool ngrok built-in. Make sure to have a look at all the options with the command
twilio serverless:start --help or read this article.
With only two commands, you were able to set up a new local serverless project that can be adjusted to specific requirements. But how do you extend the project, create new functions, and get some inspiration on how to control Twilio’s services in a serverless world?
Create new functions for other use cases
One way to add more functionality is to create additional files inside of the
assets directory. This process is somewhat manual, though. What if I told you that there was a quicker way to set up functions?
twilio serverless:new helps to reduce the number of repetitive tasks and provides a way to create new functions using pre-defined templates.
twilio serverless:new ? Select a template Hello Voice - Function to get you started with Twilio Prog. Voice Hello Messaging - Function to get you started with Twilio Prog. Messaging Never gonna give you up - Never gonna let you down. Plays a song to a phone call ❯ Forward Call - Forwards an incoming call to another number Forward Message - Forwards incoming messages to another number Forward Message to Multiple Numbers - Forwards incoming messages to a set of numbers Forward Message to Email via SendGrid - Uses SendGrid to forward incoming messages via email (Move up and down to reveal more choices)
After picking a template and a namespace directory, the setup process will create new files and give hints on other setup actions. For example, the template below requires the definition of a certain environment variable.
twilio serverless:new ? Select a template Forward Call - Forwards an incoming call to another number ? What should be the namespace your function(s) are placed under? private ✔ Configuring Environment Variables in .env ✔ Installing Dependencies ✔ Creating function: forward-call.js INFO Make sure to configure MY_PHONE_NUMBER in the .env file SUCCESS Downloaded new template into the "new-service" subdirectories
What function use cases would you like to see? All function templates are available and editable on GitHub – we’d love to hear your ideas!
After creating a new function, restart the local server by running
twilio serverless:start again. The new endpoint will be available locally. For the above function, this endpoint is
Local development is only half of the story – how do you deploy functions to the cloud, ready to scale?
Showtime – deploy, deploy, deploy!
When you’re happy with your local functions and assets run
twilio serverless:deploy to deploy them.
twilio serverless:deploy Deploying functions & assets to the Twilio Runtime Account SK6b3e6df6812298f87594567895e55ede Token kegH**************************** Service Name serverless-tryout Environment dev Root Directory /private/tmp/serverless-tryout Dependencies Env Variables MY_PHONE_NUMBER ✔ Serverless project successfully deployed Deployment Details Domain: serverless-tryout-6774-dev.twil.io Service: serverless-tryout (ZSc...) Environment: dev (ZEa...) Build SID: ZB8... Functions: [protected] https://foo-6774-dev.twil.io/sms/reply https://serverless-tryout-6774-dev.twil.io/hello-world https://serverless-tryout-6774-dev.twil.io/forward-call/forward-call https://serverless-tryout-6774-dev.twil.io/private-message Assets: [private] Runtime.getAssets()['/message.js'] https://serverless-tryout-6774-dev.twil.io/index.html https://serverless-tryout-6774-dev.twil.io/style.css
This one command deploys the code to the cloud and creates publicly available assets and function endpoints.
If you want to inspect the deployed runtime, there are two ways to do this. The first one is using the
twilio serverless:list command:
twilio serverless:list functions --service-sid=ZSc7... Account SK6b... Token kegH**************************** Service ZSc7... Environment dev Functions for environment ZEa5... │ /sms/reply [Visibility protected] │ /hello-world │ /private-message │ /forward-call/forward-call
This command accepts several configuration options so that you can inspect the exact area of your interest. If you want to see what flags are available, remember the
--help flag will be your friend.
The other way is to head to the functions API area in your Twilio console and have a look there.
A more in-depth look at the created endpoints and their new domain explicitly shows how the new Function and Assets API is structured and how it differs from the UI-only Twilio functions. Let’s have a brief look.
New power and flexibility with environments
The domain of the freshly deployed service unveils one significant improvement that comes with the new API that was not available before.
Random number \ / https://serverless-tryout-6774-dev.twil.io/sms/reply \ / \ / Service name Environment Domain suffix
The Serverless API supports environments. When you deployed your project a few minutes ago, the CLI used a default value as the environment –
dev. Every environment is represented by its own domain. To deploy another environment, use the
--environment flag with the
The environment feature may not look like a big deal now, but in the future, it will be. When you run large projects with many developers working on the same serverless codebase, environments are crucial.
Thanks to environments, you can test and deploy changes in isolation to their own domain without affecting your production setup. Then, only when you’re ready to switch, you can promote one environment to another (e.g.
prod) using the command
twilio serverless:activate. Environments are a big step towards automation and the implementation of proper CI/CD workflows – both, mandatory processes when you’re running on a bigger scale.
The automation of your Twilio setup
The new Twilio Runtime API paired with the Serverless toolkit is the missing piece to automate tasks in your existing infrastructure and even create new installations from scratch.
What if I would tell you that you can now buy numbers, create sync services, connect your communication channels via functions by running a single command? In short, do all things Twilio-related by just running a shell script. Well… I did precisely this just a few days ago, and it made me get out of my chair saying, “Hell yeah!”. Watch the space, I’ll keep you posted about how to script Twilio setups in the following tutorials. 👋
Let me know if you're as excited as me about this new API. You can reach me under the following channels.