Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express.js app serverless, using Lambda or Functions - a good idea?

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?

like image 373
marko-36 Avatar asked Dec 12 '20 15:12

marko-36


People also ask

Should you use Express with Lambda?

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.

Can we use Express with serverless?

AWS Lambda allows existing Express apps to go Serverless and so there is no infrastructure for Developers to manage.

Is Lambda really serverless?

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.

How do I convert Express app to Lambda?

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.


2 Answers

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.

like image 33
Asri Badlah Avatar answered Nov 05 '22 20:11

Asri Badlah


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:

  • In the future do I want to have some websocket connection?
  • Do I need any proxy in my request routing?
  • How big will become my application over time?
  • Which AWS Service will I expect to use in the future

Scalability

Using Express.js in a lambda is not a good idea for many reasons:

  1. You will pay more for the execution of your Lambda because it will take more time to run and maybe more memory
  2. Latency is higher
  3. Doing a small modification means redeploying all your application code on 1 lambda so only 1 point of failure.
  4. Normally overtime your application's code base will grow as you add more features. The maintenance of that monolithic repo will be a pain in the ass and you will deploy less than you want because of the bugs you might encounter.

Cost effectiveness

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

Latency

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

How to convert Express framework into plan Lambda

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

  1. Headers (JSON)
  2. statusCode (number)
  3. Body (stringified)

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:

  • https://aws.amazon.com/blogs/compute/going-serverless-migrating-an-express-application-to-amazon-api-gateway-and-aws-lambda/
  • https://dev.to/brightdevs/how-to-convert-an-express-app-to-aws-lambda--44gc
  • https://medium.com/hackernoon/how-to-deploy-a-node-js-application-to-aws-lambda-using-serverless-ae7e7ebe0996
  • https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

To Conclude

The upside of using lambdas without Express are:

  • better scalability
  • cost optimization
  • lower latency
  • higher availability because you have multiple lambda for each business logic instead of one that run it all

The downside of using lambdas without Express are:

  • You need to modify your existing code
  • Init time of your lambda needs to be part of your thinking when developing your logic
  • You need to learn SAM yaml template and read the AWS doc when you wanna add more functionality to your API infrastructure.

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

like image 191
Benjamin Filiatrault Avatar answered Nov 05 '22 22:11

Benjamin Filiatrault