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?
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.
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".