skip to Main Content

I’m working on building a NestJS API application using a monorepo approach to keep all my endpoints organized in one codebase. However, I’m facing a challenge when it comes to deploying this application to multiple AWS Lambdas, each representing a different module (like Auth, Users, Posts, etc.), and then mapping them to a unified API Gateway.

In my previous attempts, I’ve created separate NestJS projects for each module, which resulted in a maintenance nightmare due to shared code complexities. Now, I’m exploring the option of maintaining a single codebase for all modules. My goal is to deploy each module as an individual AWS Lambda function, while still keeping the codebase manageable.

So, here’s my main question: Can I achieve this setup using the Serverless Framework? I want to have a single codebase for all the modules and deploy them to separate AWS Lambdas. Additionally, I’m aiming to integrate these Lambdas under a single API Gateway to provide a unified API access point.

Any insights, advice, or examples on how to structure my Serverless Framework configuration, how to manage the shared codebase efficiently, and how to set up the API Gateway to work with these multiple Lambdas would be greatly appreciated. Thank you in advance for your help!

2

Answers


  1. Create two repos: one for your NestJS Application and one for the AWS infrastructure.

    In your NestJS App, add your APIs (Auth, Users, Posts, etc) but do not implement them there. In those APIs, add calls to your AWS Lambdas. Your main logic will happen in Lambdas as you requested.

    In the infrastructure package (I recommend using AWS CDK), create an API Gateway. For each API endpoint (Auth, User, etc), create a resource. For each resource, add the method (POST, GET) and attach a Lambda function.

    This approach will be very manageable. You will have two code packages. One for the front-end and one for the back-end.

    You can add as many APIs as you want and you will have a single API Gateway (unified) that will handle them all.


    AWS CDK Examples for the unified API Gateway

    // API Gateway
    const api = new RestApi({});
    
    // Add resources
    const auth = api.addResource('auth');
    const users = api.addResource('users');
    
    // Attach Lambda to the endpoint
    auth.addMethod('POST', AuthLambdaIntegration...)
    users.addMethod('POST', UserLambdaIntegration...)
    
    Login or Signup to reply.
  2. Interesting. I’m trying to achieve the same. What I did in my scenario with turborepo, was installing serverless-nest-monorepo which does pretty much what you want if you check the docs. Then you can just integrate the command in your CI to deploy the lambda or deploy on your machine. However, It doesn’t seem to be working with nestjs 16 properly by reading the issues…

    There are also other tools such as serverless-plugin-monorepo but I had a bug using it. It seems that dependencies of dependencies are not being loaded into the lambda function.

    The major problem that I’m having with trying to deploy multiple NestJS applications in a monorepo is that all their dependencies are inside the root node_modules and this means that using just serverless deploy doesn’t work because it doesn’t add all the dependencies necessary. And that is some of the reason why the 2 plugins I listed before exist. You can try disabling hoisting, that should do the trick, but it will make it very slow to build everything.

    You could also try using AWS CDK to manage these deploys, it might be easier that handling the serverless npm module to understand your monorepo.

    After some tinkering, what worked for me was the following serverless.yml file inside each application of my turborepo:

    service: serverless-example
    
    provider:
      name: aws
      runtime: nodejs18.x  
      profile: my-profile
      region: us-east-1
    
    
    plugins:
      - serverless-plugin-typescript
      - serverless-tscpaths # must be after serverless-plugin-typescript
      - serverless-offline  
      - serverless-plugin-optimize
    
    package:
      patterns:
        - '!test/**'
        - '!insomnia/**'
        - '!docst/**'
    
    
    functions:
      main:
        handler: src/lambda.handler
        events:
        - http:
            cors: true
            path: '/'
            method: any
        - http:
            cors: true
            path: '{proxy+}'
            method: any
    
    

    One thing to notice, is that I’m using yarn and had to disable hoisting. Hoisting would put the dependencies of each application inside the root project folder and they would not be inserted into the lambda package after sls package and this breaks the lambda. with an "import unresolved" error in aws.

    To disable hoisting with turborepo, in the package.json in root, add this:

      "workspaces": {
        "packages": [
          "apps/*",
          "packages/*"
        ],
        "nohoist": [
          "**"
        ]
      }
    
    

    With this setup, test it with serverless offline first locally, running it no the folder of each application, make some calls to your lambda and then serverless deploy and everything should be all right.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search