Migrating Functions from callback to async/await
Starting with Node.js 24, AWS Lambda no longer supports callback-based function handlers. If you're on Twilio's Runtime Handler 2.1.2 or above, your existing callback-style Functions continue to work on all runtimes without code changes. Twilio recommends migrating to async/await regardless.
Info
Async/await requires Runtime Handler 2.1.2 or above on all runtimes, including Node.js 22. See the Runtime Handler page for how to update.
Previously, Twilio Functions used a callback pattern to signal completion. To make an async API call, you had to use .then()/.catch() chains:
1exports.handler = (context, event, callback) => {2const client = context.getTwilioClient();3client.messages4.create({ to: event.To, from: event.From, body: 'Hello!' })5.then((message) => {6return callback(null, message.sid);7})8.catch((error) => {9return callback(error);10});11};
With async/await, you can use await directly inside the handler:
1exports.handler = async (context, event, callback) => {2const client = context.getTwilioClient();3try {4const message = await client.messages.create({5to: event.To,6from: event.From,7body: 'Hello!',8});9return callback(null, message.sid);10} catch (error) {11return callback(error);12}13};
Info
The callback parameter is still available and fully supported. Adding async to your handler signature is the minimum change required — it lets you use await inside your function. You can continue calling callback to return your response, or you can return a value directly and Twilio's runtime-handler will handle it automatically.
No async operations — just add async to the signature.
1exports.handler = (context, event, callback) => {2const twiml = new Twilio.twiml.MessagingResponse();3twiml.message('Hello, World!');4return callback(null, twiml);5};
1exports.handler = async (context, event, callback) => {2const twiml = new Twilio.twiml.MessagingResponse();3twiml.message('Hello, World!');4return callback(null, twiml);5};
Replace promise chains with await and try/catch.
1exports.handler = (context, event, callback) => {2const client = context.getTwilioClient();3client.messages4.create({ to: event.To, from: event.From, body: 'Hello!' })5.then((message) => {6return callback(null, message.sid);7})8.catch((error) => {9return callback(error);10});11};
1exports.handler = async (context, event, callback) => {2const client = context.getTwilioClient();3try {4const message = await client.messages.create({5to: event.To,6from: event.From,7body: 'Hello!',8});9return callback(null, message.sid);10} catch (error) {11return callback(error);12}13};
With an async handler, you can also return a value directly without calling callback. The runtime-handler detects the returned Promise and handles it automatically.
1exports.handler = async (context, event) => {2const twiml = new Twilio.twiml.MessagingResponse();3twiml.message('Hello, World!');4return twiml;5};
Warning
Do not both call callback and return a value in the same handler. While the runtime-handler guards against double responses, it is still confusing and error-prone. Pick one approach and use it consistently.
With the callback pattern, errors are passed as the first argument to callback. With async/await you can throw an error instead — if you are returning values directly rather than calling callback.
1exports.handler = async (context, event, callback) => {2try {3const result = await someAsyncOperation();4return callback(null, result);5} catch (error) {6return callback(error);7}8};
1exports.handler = async (context, event, callback) => {2const result = await someAsyncOperation(); // throws on failure3return result;4};
| Callback style | Async/await style | |
|---|---|---|
| Handler signature | (context, event, callback) | async (context, event, callback) |
| Return a response | callback(null, twiml) | callback(null, twiml) or return twiml |
| Return an error | callback(error) | callback(error) or throw error |
| Async operations | .then().catch() | await + try/catch |
| Node.js 24 support | No | Yes (requires runtime-handler 2.1.2+) |
- Function execution — detailed reference for the
context,event, andcallbackparameters - Runtime Handler — runtime-handler versions and how to update
- Node.js v22 upgrade — upgrading your runtime version
- AWS Lambda Node.js handler reference — AWS documentation on the callback removal in Node.js 24