Some facts why usage Express.js inside AWS Lambda is pitiful design anti-pattern and how to give it up without pain.
Last few years popularity of NPM packages, that allow you to use Express.js inside AWS Lambda handler, grow up rapidly. These packages provide some functionality that allows you to run Express.js middlewares, controllers with some limitations, instead of plain AWS Lambda handler.
Some examples of such libraries:
But why developers decided to do so? They’re just a few foremost reasons, that I’ve usually met in practice:
So below the list of reasons why the usage of Express.js inside AWS Lambda in most cases are redundant, you probably get many drawbacks from this approach.
Simple point — the bigger node_modules do your artifact have, the bigger cold starts of AWS Lambda will you have. With no exceptions. Raw Express.js is near 541.1 KB, but you also need additional dependencies, mostly middleware, that can increase your node_modules several times.
When you use standalone Express.js on the server (standard way), each HTTP request is some kind of text that the server parses to a well-known request object. Lambdas that people tried to use with Express.js inside, usually runs under API Gateway or AWS Application Load Balancer, and data that come from this event source are already parsed by API GW and ALB! Yes, it’s different, but anyway.
When you use Express.js inside AWS Lambda your “system” make the next thing with input HTTP data:
So many supplementary conversions. Sometimes it looks like just wasting processor time.
Despite all disadvantages, the embedded middleware pattern in Express.js is probably one of the popular things in the Node.js world. However, there is no need to use Express.js just for this, coz at least one middleware library is suited for AWS Lambda better: @middy/core
Also, it implements an onion-like middleware pattern, that is much more flexible than Express.js can provide for you.
At least you can easily find out the next point — security protection approaches are different. When Express.js best practice guide proposes to use Helmet.js library, it doesn’t applicable to AWS Lambdas. AWS proposes to use AWS WAF service that:
Protect your web applications from common web exploits
When you write classic AWS Lambda handlers, you usually can package each lambda artifact separately, to reduce each artifact size. But when you use Express.js, you cannot do this — all lambdas require the same dependencies. Technically you can, but all of them will have the same size, which negates their advantages. Also, in this case, serverless-webpack-plugin cannot optimize imports correctly, because technically each lambda will have the same dependencies tree
Despite all of the above, I believe, that there some cases when the usage of Express.js inside AWS Lambda are valid and justified:
Hope this information will be useful and you will not forget this when decide to use Express.js inside AWS Lambda the next time.