Disclaimer: I admit this is more of a broad-ish best practice question, rather then a specific programming issue, however, I believe the SO bunch is the best audience for it. I am aware of this similar question (Should I be using Express.js in a Serverless app?), but the answers don't seem to answer mine.
I want to move an Express.js from AWS Lightsail/EC2 to serverless for typical reasons, and Lambda is my weapon of choice. However, a whole framework together with an app on top of it may be a bit hefty to be still considered a function and so possibly unsuitable to be run as such on AWS Lambda, or Google/Azure Functions. While I'm convinced it is doable, is it a good idea? Wouldn't this setup kill efficiency and complicate handling things such as sessions states, ultimately defeat the purpose of serverless functions?
Using Express. js in a lambda is not a good idea for many reasons: You will pay more for the execution of your Lambda because it will take more time to run and maybe more memory. Latency is higher.
AWS Lambda allows existing Express apps to go Serverless and so there is no infrastructure for Developers to manage.
AWS Lambda is a serverless, event-driven compute service that lets you run code for virtually any type of application or backend service without provisioning or managing servers. You can trigger Lambda from over 200 AWS services and software as a service (SaaS) applications, and only pay for what you use.
The best way to fixes this is to create a new API Gateway endpoint. Because it is one time only let's create it using the AWS website. After login navigates to API Gateway. Set Lambda Integration to true and select your region and then select our function in the Lambda Function.
If it's a bit hefty to be function as you said, you may think in creating a docker image for your app and run it using Fargate ECS which is considered a serverless option.
The answer to your question depends upon your current and future needs. I think you should always plan ahead and make sure that the current infrastructure that you will implement can be upgradable for future needs.
You should ask yourself those questions:
Using Express.js in a lambda is not a good idea for many reasons:
Express.js on Lambda is more expensive because you need to proxy any method into your lambda using a API Gateway REST API rather then using API Gateway HTTP API
HTTP APIs are up to 71% cheaper compared to REST APIs
Lambda isn't magically executing your code without server even tho they market it like it is. When an event occur, AWS will launch a docker container, wait for it to fully load all your dependencies and then run your handler.
With a normal Node.js server on AWS EC2 or AWS ECS it's a one time cost because your server is always running and all your dependencies are already loaded but not on your lambda.
As AWS says:
This approach [Express.js and proxy all requests to your lambda] is generally unnecessary, and it’s often better to take advantage of the native routing functionality available in API Gateway. In many cases, there is no need for the web framework in the Lambda function, which increases the size of the deployment package. API Gateway is also capable of validating parameters, reducing the need for checking parameters with custom code. It can also provide protection against unauthorized access, and a range of other features more suited to be handled at the service level.
Best practices for organizing larger serverless applications
To simplify your life, I would suggest you to use SAM CLI. It's very simple to get started with it.
Install SAM CLI
If you're following the MVC pattern for your Express app. You only need to take your service files where your core logic live.
The folder structure I like to use for the lambda is the following
Suppose it's a small calendar app
──src-ts
├───handlers
│ getEvent.ts
│
├───tests
│ │ getEvent.tests.ts
│ │
│ └───utils
│ utils.ts
│
└───utils
utils.ts
validation.ts
It's important that your handler returns 3 thing
You also need a template.yml
file to describe the infrastructure that your lambda need
AWSTemplateFormatVersion: 2010-09-09
Description: Describe the lambda goal
Transform:
- AWS::Serverless-2016-10-31
Resources:
# API Gateway
LambdaAPI:
Type: AWS::Serverless::Api
Properties:
StageName: StageName
Cors:
AllowMethods: "'POST, GET, OPTIONS'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
# IAM Role
LambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 'sts:AssumeRole'
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
- arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess
GetEvent:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs12.x
Timeout: 180
FunctionName: youLambdaName
Handler: src/handlers/getEvent.handler
Role: !GetAtt LambdaRole.Arn
Events:
Get:
Type: Api
Properties:
RestApiId: !Ref LambdaAPI
Path: /events/{eventid}
Method: GET
Note
I used typescript and but when compiled it's creating an src
folder
Some resource to help you more in depth:
The upside of using lambdas without Express are:
The downside of using lambdas without Express are:
Take advantage of the AWS infrastructure, don't try to go against it. All AWS Services are working together in a seamless and low latency way. You should remove Express from your infrastructure if you wanna go "Serverless".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With