End of AWS Lambda support for Node.js 10: should you switch straight to v14?
Published: 2021-05-17 14:22:16

*It's the end of AWS Lambda support for Node.js v10. AWS Lambda support for Node.js 10 is due to end in August 2021. It's time to switch! In this article, we're discussing and comparing the differences of working with Node.js 10 and Node.js 14 + AWS Lambda, the impacts, and benefits of this change.*

*Original article with code snippets here: *[*https://dashbird.io/blog/aws-lambda-nodejs-10-vs-14/*](https://dashbird.io/blog/aws-lambda-nodejs-10-vs-14/)

![](https://miro.medium.com/max/2000/1*E8FH9oM5cCc_l6D8thCsYQ.png)

AWS Lambda supports multiple versions of programming language runtimes, but not forever. That's because the creators of these programming languages don't support them infinitely either.

AWS Lambda also only supports the long-term support (LTS) versions of Node.js: the even version numbers. Currently, versions 10, 12, and 14 are all supported, but in August 2021, the support for version 10 is running out.

So it's time to switch, but besides evading the support end, what benefits does it bring to switch directly to version 14? In this article, I will go over the changes that have happened since version 10 of Node.js.

![](https://miro.medium.com/max/2048/0*WG9yZQSNcaXoM1_n.png)

What Features were Added Since Version 10?
==========================================

Let's start with the ECMAScript additions to JavaScript. Usually, they are supported in the JavaScript engine before they are standardized. The idea is that nothing, that isn't working in practice, gets standardized.

This doesn't mean that all JavaScript engines support every ECMAScript feature before it is standardized. After all, the committee can't wait for every JavaScript engine that is out there. For example, proper tail call optimization is standardized for years now, but only a few engines have implemented the feature.

Anyway, let's check what happened since version 10!

Optional Chaining and Nullish Coalescing
========================================

This is one of the biggest additions, in my opinion. Gone are the crashes because you tried to access an attribute of an undefined variable, or you set a default for a value that was null-ish.

The optional chaining operator `?.` is an alternative to the regular chaining operator `.` they can be used all the same; the only difference is that the regular chaining operator will crash if you try to access an attribute on an undefined variable. The optional chaining operator will simply return `undefined`.

![](https://miro.medium.com/max/1912/1*ykkzbaw43E7tPIGoNO8mjw.png)

If at least one part of this chain isn't an object, `deepValue` will be set to `undefined`.

The nullish coalescing operator `??` is an alternative to the logical or operator `||` used to set variables to a default value.

The problem with the logical or operator was that it also used the default when the value was something that could be automatically converted to `false`, like the number `0`. The nullish coalescing operator would only use the default when the checked variable was null or undefined.

![](https://miro.medium.com/max/2772/1*4qJ4ciRJv_lescKerY5hFA.png)

In the example, the logic or operator would set the amount to `20` even if the `input` was `0`, but the coalescing operator would leave it at `0`.

The two new operators work nicely in tandem.

![](https://miro.medium.com/max/2200/1*jLD6-4wR5rrtW-1y24FedA.png)

Symbol Additions
================

The Symbol class got two new additions. If you create a new symbol with a description, you can now check it later with the description property.

This example will log "`description`" to the console.

![](https://miro.medium.com/max/2800/1*oSrnJMmXyGJCvbANPMck4Q.png)

There is also a new well-known symbol called `matchAll`. It can be used to create custom matchAll functions for your data types.

![](https://miro.medium.com/max/2796/1*Txta38YUp5QZnDBhcDALWw.png)

The object `numbers` needs a generator function (that's what the `*` means) in its `Symbol.matchAll` property, so it can be used as a parameter for the `String.prototype.matchAll` method. This example will output `["2021", "05", "12"]`.

Global This
===========

The unification of `window`, `self`, `frames`, and `global` into one global object called `globalThis`. Back in the days, the access to the global object differed from where your script was running, but if you tried to access `window` inside Node.js or a worker thread, it would fail. With `globalThis` your script doesn't have to care anymore.

This example works in all current browser versions and Node.js:

![](https://miro.medium.com/max/1236/1*RoqP37AiyEmKx_jPurnVsg.png)

Class Fields
============

Since Node.js 10, there have been some additions to classes as well: instance class fields, static class fields, and private class fields.

Before version 12, instance fields had to be set in the constructor, and static fields had to be set via the prototype, and both were always public. Now you can set them all in the class definition and modify their visibility.

Let's see how it works in practice:

![](https://miro.medium.com/max/2796/1*fRfD-ybNFym6Lm_uZHveyQ.png)

Flattening Arrays
=================

If you end up with a nested array, and you want to lift the nested elements back to the top array, the new `flat` method for arrays is the solution.

![](https://miro.medium.com/max/2784/1*ZNqH3zHCBBcztz3zpKSYEA.png)

The example above, flattened, will contain `[1, 2, 3, 4, 5, 6, 7]`. But keep in mind that it only flattens a depth of one; you have to call it again if you have deeper nested arrays you want to get rid of.

Since the `flat` method is usually called to clear up the array structure before a call to the `map` method, a shortcut method called flatMap() will work as a `map` with a `flat` applied before.

In the following example, the item is always a number and never an array because the nested array is flattened before passed to the callback function.

![](https://miro.medium.com/max/2764/1*1rNl2B0_vCJXK7MHQxAQeQ.png)

International Display Names
===========================

The new Intl.DisplayNames API allows to translate region, language, and script display names automatically.

This would display "德文", the traditional Chinese translation of the language "German".

![](https://miro.medium.com/max/2784/1*vEKlWb-BeGAvWQmT9QhmJw.png)

Numeric Separators
==================

It's now possible to add underlines to number literals to make them more readable inside the code.

![](https://miro.medium.com/max/2788/1*BGqrYMzib8t8TmSmDKucIQ.png)

Performance Improvements
========================

Since version 10, many performance improvements have happened. The startup time improved by 30%, which can shave quite some time from your [cold start latency](https://dashbird.io/blog/can-we-solve-serverless-cold-starts/).

The heap size configuration was done with two default values before, but in version 14, Node.js will take the actual available memory into account when configuring the optimal heap size. Since AWS Lambda allows for very flexible memory configurations per function, this could help you get more bang for the buck.

> Find out more about saving money on Lambdas in our [6 AWS Lambda Cost Optimization Strategies That Work](https://dashbird.io/blog/aws-lambda-cost-optimization-strategies/) article.

I tried a prime number calculation on AWS Lambda with Node.js 10 and 14 to see the differences. First, I calculated primes between one hundred and one thousand and then those between one hundred and one billion. I run this with 128MB and 1024MB memory configuration, to see how the init times and runtime durations changed between the two versions.

The following graphs illustrate the differences.

![](https://miro.medium.com/max/1200/0*auQcMl408b1sYQVX)

Blue marks Node.js 10 and red 14. As you can see, the init timings got better by ~20% and I just switched the runtime version. Because Lambda functions are billed by millisecond this is real money you can save. Also, short-running Lambda functions can reduce the latency quite a bit.

![](https://miro.medium.com/max/1200/0*NKcm394WC0bd7ZtL)

Again, blue marks Node.js 10 and red 14. This time I measured the duration an invocation took. The difference between the primes between hundred and thousand wasn't much, so I left them out here, but for longer computations, like finding the primes between one hundred and one billion, it makes a huge difference. This saves a huge chunk of money and could even make it possible to do slow calculations synchronously as an API Gateway response now.

Other Additions
===============

The [diagnostic reports](https://nodejs.org/docs/latest-v14.x/api/report.html) help with analyzing the behavior of a Node.js program. It will log out a JSON formatted string into a file that you can check for more details than CloudWatch gives you.

> Find out how you can get even [more detailed and faster AWS data analytics, observability and debugging](https://dashbird.io/blog/cloudwatch-vs-dashbird/).

TLS 1.3 and QUIC protocol support have landed in the LTS version of Node.js, so your Lambda can keep communicating with the latest services out there.

The [worker threads API](https://nodejs.org/docs/latest-v14.x/api/worker_threads.html) is now stable. You can use it for computation-intensive workloads. Usually, Node.js is a single-threaded environment, but you can now execute JavaScript with worker threads in parallel. When you configure Lambda memory, the vCPU cores are also configured implicitly. If you set a memory limit of 10 GB, you also get 6 vCPU cores, which you can now utilize with Node.js worker threads.

Full International Components for Unicode (ICU) support has landed in Node.js. ICU is a set of "libraries providing Unicode and Globalization support for software applications". The full list of features can be found [on Node.js's GitHub Repository](https://github.com/nodejs/node/blob/master/doc/api/intl.md).

Conclusion
==========

The sun is setting on the LTS for Node.js version 10 in a few months' time, and so is the AWS Lambda runtime support. If you have to switch anyway, why not go straight to version 14? It will give you a longer support time in the future, and you get a whole bag of extra features that improve the coding of Lambda functions and their performance on the AWS platform.

*Further reading:*

[AWS Lambda Node.js errors and exceptions](https://dashbird.io/event-library/aws-lambda/aws-lambda-node-js-errors-and-exceptions/)

[How to deploy a Node.js application to AWS Lambda using Serverless](https://dashbird.io/blog/how-to-deploy-a-nodejs-application-to-aws-lambda-using-serverless/)

[AWS Lambda metrics you should definitely monitoring](https://dashbird.io/blog/lambda-metrics-monitoring-what-matters/)