AWS Lambda nodejs10.x = FIXED 🎉

Michael Hart
3 min readJun 25, 2019

A month ago I dug into the nodejs10.x runtime and highlighted some issues with it — including some bugs and style problems. I’m glad to now report that all the issues I raised have been addressed in the latest runtime code, which should be running on all nodejs10.x Lambdas as of the time of writing.

There are also couple of changes that will break functions using relative handler paths and relying on logs preserving newlines — I cover these further down.

To summarize briefly how the issues were addressed:

  • The env vars in bootstrap are now named correctly, AWS_LAMBDA_FUNCTION_MEMORY_LIMITAWS_LAMBDA_FUNCTION_MEMORY_SIZE, --max_semi_space_size--max-semi-space-size, --max_old_space_size--max-old-space-size
  • String quotation marks are now standardized (they chose double-quotes, boo… #team-single-quotes). There are a number of other formatting changes that suggest they’re now using a linter like eslint and a formatter like prettier, which I highly recommend to any JS team — the fewer style arguments (and diversions) the better.
  • An unhandledRejection handler has been added — and top-level errors are now logged as they were in previous runtimes, which caught a few people out.
  • The beforeExit bug in index.js regarding work done outside the handler has been fixed — essentially runtime.scheduleIteration() is now explicitly called on startup as well on beforeExit, so it doesn’t matter if the event loop never becomes empty and beforeExit never fires.
  • Handlers that use a callback will no longer erroneously use the return value of the handler function instead of the value passed in the callback. The explicit call to callbackContext.succeed(result) in Runtime.js after function invocation was removed, leaving the callback to handle success/failure itself.
  • All asynchronous functions now use callbacks correctly 🎉 There are no more cases of functions being called serially without waiting for the previous result, and all callback functions now have callback parameters. This is GREAT to see, and should avoid any hard-to-track-down bugs in the HTTP handling code.

Breaking changes

As I mentioned before, there are SOME changes that may break (or already have broken?) existing functions if you were relying on either of the following:

  • Relative handlers (eg, ../../opt/index.handler) — these no longer work and will throw an exception. Alternatively you can use an absolute handler, eg /opt/index.handler.
  • Newlines in log output. This is an unfortunate change IMO — newlines(\n) in console.log() statements are now replaced with carriage returns (\r) . This means any object logging, or formatted JSON strings you were outputting will now be transformed, potentially irreversibly. If you’re parsing these logs using CloudWatch, you’ll need to update your parsing code, OR add the following to your lambda to revert to the log formatting from previous runtimes:

const { logger, appenders, layouts } = require('lambda-logging')
logger.appender = new appenders.ConsoleAppender(
new layouts.Node4LegacyLayout()
)

There are a lot of other changes to the lambda-logging module, which AFAICT isn’t documented anywhere. I personally think log formatting should be left up to individual functions, and the way the runtime messes with console.log and the overhead of including this module in everyone’s Lambda isn’t worth it. Hopefully AWS will document this module soon in any case.

Conclusion

I’m glad to see that AWS has updated this runtime, and the code looks in much better shape for it.

I’m now lifting my previous caution and suggest everyone give it a shot — watch out for the logging changes, but aside from that, launch away! 🚀

--

--

Michael Hart

Principal Engineer at Cloudflare. Previously: VP Research Engineering at Bustle, AWS Serverless Hero, creator of LambCI. github.com/mhart