With the state of serverless growing at an exponential rate during the last year, it’s no surprise developers across the globe have flocked to use AWS Lambda as their main serverless compute engine. AWS has a steady track record of covering all the main needs of developers, DevOps engineers and even C-level tech executives. Hell, I’ve been using it for a couple of years, and still haven’t come close to check out even half of their offering.
Disappointment turned to joy
So, after all that, tell me, why haven’t we had the joy of using the newest version of Node.js on AWS Lambda? Strange indeed. The de facto go-to compute service for serverless has limited Node.js developers to use outdated versions of their favorite language *sad face*. All that changes now, with the public release of a new supported version of Node.js. To be more precise, it’s version 8.10
. We now finally have beloved features at our disposal running natively in the AWS Lambda runtime. Praise all things holy!
Out with the old, in with the new
Remember that clunky callback
parameter every lambda function has? Here’s some pseudo code showing a generic login function.
Note: Examples are written in Node.js using the Serverless Framework.
// Node.js v.6.10 | |
module.exports.login = (event, context, callback) => { | |
connectToDatabase() // promise | |
.then(() => | |
login(JSON.parse(event.body)) // promise | |
) | |
.then(session => callback(null, { // stupid callback 🙁 | |
statusCode: 200, | |
body: JSON.stringify(session) | |
})) | |
.catch(err => callback(null, { // stupid callback 🙁 | |
statusCode: 500, | |
body: JSON.stringify(err) | |
})); | |
}; |
Yeah, well now you don’t need callback
s anymore! With this new Node.js version the Gods of AWS have given us the possibility to leverage Promise
chains for lambda handlers. Remember those wrappers you used to write to handle promises? Yes, those… Well, you can throw them out and just return a Promise
chain now. Don’t believe me? Check it!
// Node.js v.8.10 | |
module.exports.login = (event, context) => { | |
return connectToDatabase() // returning promise! 🙂 | |
.then(() => | |
login(JSON.parse(event.body)) // promise | |
) | |
.then(session => ({ // resolving the promise to an object | |
statusCode: 200, | |
body: JSON.stringify(session) | |
})) | |
.catch(err => ({ // or rejecting with an error | |
statusCode: 500, | |
body: JSON.stringify(err) | |
})); | |
}; |
How amazing is this!? No more fiddling with annoying callbacks. Using Promises
natively and chaining them in the same way you’re already used to in your day-to-day life is just a breath of fresh air for serverless developers worldwide.
My life has just become 40% more joyful, just by starting to use Promises
in my lambda functions. If you want to know why exactly 40%, hit me with a comment below. I may be joking, just a bit. *wink* *wink*
What about the fancy new ES6+ syntax?
Okay, so using Promises
is amazing, but that’s not all. You know about my good friend async
and his twin brother await
? Yeah, I had a chat with them a while back and to be honest, they’re thrilled to finally be invited aboard the serverless hype train. *crowd cheers*
Now you can make your lambda function async
and await
every particular asynchronous piece of code within the lambda itself! Have a look below.
module.exports.login = async (event, context) => { // Lambda is async! | |
try { | |
const db = await connectToDatabase(); | |
const session = await login(JSON.parse(event.body)); | |
return { | |
statusCode: 200, | |
body: JSON.stringify(session) | |
}; | |
} catch (error) { | |
console.error(error.stack); | |
return { | |
statusCode: 500, | |
body: JSON.stringify(error.message) | |
}; | |
} | |
}; |
That is so sexy! Finally a reason to use try/catch
blocks in JavaScript! I haven’t seen one of those since 2015 when I last tortured myself with C#. Good times. Hope to forget them as soon as possible.
With synchronous-looking code you get much better error handling and general visibility. The code is flat without any excessive indents. Using the try/catch
block inside an async
function will make sure all errors are handled even if the scope of the function is awaiting asynchronous operations.
Porting your existing functions from Version 6.10
to 8.10
can cause some issues, but for the most generic use cases you’ll be just fine. But to be safe, make sure to test your ported functions first, before you start routing production traffic to them. It also helps to write tests cases and even test things locally. Once you’re confident, and deploy it all, Dashbird will help you get a bird’s eye perspective of all your functions. You can rest assured we’ve got your back.
Make sure to specify the new version
While configuring the Serverless Framework for local development, like every other sane human being, you need to specify the runtime underneath the provider
section. Like this.
# serverless.yml | |
… | |
provider: | |
name: aws | |
runtime: nodejs8.10 | |
stage: dev | |
… |
Or if you like torture, and create your lambda function through the AWS Console, specify the version during the actual creation.
Having an overview of your Node.js versions
We at Dashbird have done our best to give you the ability to see which language and runtime is running inside your lambda functions.
With a clear overview of all your functions you can see key info including the runtime.
Another cool thing you can do is to deploy the same functions but with different runtimes. This will let you monitor their execution (even in real-time) and see where they fail because of differences in the runtime! Call me a nerd, but this is so cool.
Why would you want the new runtime?
The key reasons are simple. New things are shiny and better. That would be the layman’s explanation. But in all honesty, it often is the case. Compared to the previous Node.js LTS version, Version 6.x, performance has been boosted by ~20%
. Even AWS themselves claim the new V8 6.0 engine will lower memory consumption and guarantee a faster startup time across Node.js lambda functions!
Apart from the engine itself, HTTP/2 has been introduced, making the web as a whole so much better. The new protocol fixes a vast number of workarounds and issues HTTP/1.1 had. We can now be confident our apps running on AWS Lambda will be simpler, and much faster! Unfortunately we still have to wait for AWS to provide us with HTTP/2 support for AWS API Gateway to fully leverage this feature.
I can’t wait to start building with Node.js Version 8.10! My gut tells me you’re eager too.
We aim to improve Dashbird every day and user feedback is extremely important for that, so please let us know if you have any feedback about these improvements and new features! We would really appreciate it!