iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💭

Running NestJS on AWS Lambda

に公開

I want to run NestJS on Lambda

While there are some critical opinions, I believe the benefits outweigh them, so I'll briefly summarize the pros and cons and how to get it running. In the worst case, I might end up migrating to ECS, but if I build it with NestJS, the transition should be relatively easy.

Overview

Are there any predecessors?

There are plenty. Although it might seem like an unconventional idea at first glance, its effectiveness seems reasonably well-established.

Expected Benefits

Let's organize the expected benefits. The following points can be raised:

  • Managing and deploying becomes straightforward as there is only one Lambda function.
  • Branching for HTTP methods like GET and POST can be achieved using the framework's routing features rather than within the Lambda function (which may improve code readability).
  • Express plugins can be used (leveraging the ecosystem).

Expected Drawbacks

Also, the following are raised as drawbacks or criticisms, but counterarguments can be made:

  • It is a hacky configuration; wouldn't it be better to use ECS? There are also issues with concurrency.
    -> Lambda allows for scaling to zero, which provides a cost benefit.
    -> Since it's implemented using a framework, migrating to ECS should be relatively easy, so it can be handled that way in the worst-case scenario.
  • Isn't it a disadvantage that you can't configure AWS policies per function?
    -> Depending on the requirements, it can be covered to some extent by adding role-based authorization using Guards or similar.

What does the official NestJS documentation say?

They don't seem to either recommend or discourage it, but they do mention how to run it and measures for cold starts.
https://docs.nestjs.com/faq/serverless#serverless

How to run it

I will note down only the essentials.

Required libraries

The following are required for production:

  • @vendia/serverless-express
  • aws-lambda

Also, the following are useful for development (you can also use AWS SAM, so it's a matter of preference):

  • serverless
  • serverless-offline: For local testing

Implementation and configuration

You can run it as is by following the official documentation, so please refer to that for the most part. I'll briefly introduce the steps here.

You will need to add the following configurations to serverless.yaml (some parts omitted). The key point is to set method to ANY and path to {proxy+} to accept all requests.

...
plugins:
  - serverless-offline

functions:
  XXXX:
    handler: dist/main.handler
    events:
      - http:
        method: ANY
        path: /
      - http:
        method: ANY
        path: '{proxy+}'

The following is a direct copy-paste from the official documentation, but you need to add a handler function to main.ts as shown below (this corresponds to dist/main.handler mentioned above).

import { NestFactory } from '@nestjs/core';
import serverlessExpress from '@vendia/serverless-express';
import { Callback, Context, Handler } from 'aws-lambda';
import { AppModule } from './app.module';

let server: Handler;

async function bootstrap(): Promise<Handler> {
  const app = await NestFactory.create(AppModule);
  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress({ app: expressApp });
}

export const handler: Handler = async (
  event: any,
  context: Context,
  callback: Callback,
) => {
  server = server ?? (await bootstrap());
  return server(event, context, callback);
};

The following addition is required in tsconfig.json (Reference: Enabling CommonJS modules with TypeScript's esModuleInterop flag):

"esModuleInterop": true

After building, run $ npx serverless offline and you can verify the behavior at the localhost:3000/dev endpoint (alternatively, you could just deploy it to a sandbox environment with $ sls deploy).

Conclusion

It should be very effective.

Discussion