{"id":14978669,"url":"https://github.com/klarna-incubator/nest-lambda-microservice","last_synced_at":"2026-01-27T11:09:46.295Z","repository":{"id":249122600,"uuid":"619801574","full_name":"klarna-incubator/nest-lambda-microservice","owner":"klarna-incubator","description":"Custom transporter implementation for running NestJS based applications on AWS Lambda.","archived":false,"fork":false,"pushed_at":"2025-12-12T15:21:56.000Z","size":1643,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-14T01:56:47.180Z","etag":null,"topics":["aws","aws-lambda","framework","javascript","microservice","nest-framework","nest-js","nestjs","serverless","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/klarna-incubator.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-27T13:20:04.000Z","updated_at":"2025-12-12T15:22:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"7210c2ce-bd3f-4719-bca1-c32cc5d3e682","html_url":"https://github.com/klarna-incubator/nest-lambda-microservice","commit_stats":{"total_commits":38,"total_committers":3,"mean_commits":"12.666666666666666","dds":0.1578947368421053,"last_synced_commit":"dcc697f65e08142864e9b76ad2f5b76c66f5fe8e"},"previous_names":["klarna-incubator/nest-lambda-microservice"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/klarna-incubator/nest-lambda-microservice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klarna-incubator%2Fnest-lambda-microservice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klarna-incubator%2Fnest-lambda-microservice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klarna-incubator%2Fnest-lambda-microservice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klarna-incubator%2Fnest-lambda-microservice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/klarna-incubator","download_url":"https://codeload.github.com/klarna-incubator/nest-lambda-microservice/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klarna-incubator%2Fnest-lambda-microservice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28812371,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T07:41:26.337Z","status":"ssl_error","status_checked_at":"2026-01-27T07:41:08.776Z","response_time":168,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-lambda","framework","javascript","microservice","nest-framework","nest-js","nestjs","serverless","typescript"],"created_at":"2024-09-24T13:58:10.166Z","updated_at":"2026-01-27T11:09:46.274Z","avatar_url":"https://github.com/klarna-incubator.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nest Lambda Microservice\n[![main](https://github.com/klarna-incubator/nest-lambda-microservice/actions/workflows/main.yml/badge.svg)](https://github.com/klarna-incubator/nest-lambda-microservice/actions/workflows/main.yml)\n[![Build Status][ci-image]][ci-url]\n[![License][license-image]][license-url]\n[![Developed at Klarna][klarna-image]][klarna-url]\n\n\u003e Custom transporter implementation for running NestJS based applications on AWS Lambda.\n\n\u003cimg src=\"assets/nest-lambda-microservice.jpg\"/\u003e\n\nThe **Nest Lambda Microservice** is a custom [NestJS transporter](https://docs.nestjs.com/microservices/custom-transport) solution that enables writing NestJS applications to process events on [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html).\n\n# Table of contents\n- [Overview](#overview)\n- [Pattern Matching](#pattern-matching)\n- [Message Processing](#message-processing)\n- [Release History](#release-history)\n- [License](#license)\n\n## Overview\nIn addition to the traditional HTTP style architecture, NestJS framework support writing microservice applications that use transport layers other than HTTP.\nThis library implements a custom transporter for AWS Lambda, enabling NestJS applications running on AWS Lambda to process events from various sources (SNS, SQS, AWS Gateway, etc.) using all the concepts NestJS supports such as \n- [dependency injection](https://docs.nestjs.com/fundamentals/custom-providers)\n- [decorators](https://docs.nestjs.com/custom-decorators)\n- [exception filters](https://docs.nestjs.com/exception-filters)\n- [pipes](https://docs.nestjs.com/pipes)\n- [guards](https://docs.nestjs.com/guards)\n- [interceptors](https://docs.nestjs.com/interceptors)\n\nA Nest Lambda Microservice application is composed of a client, a broker and a server.\n\nThe client provider exposes a public method `processEvent(event: unknown, context: Context)` that is invoked by the Lambda handler.\nBased on the event source, the event is mapped into one or multiple messages and published to the broker, e.g. an API Gateway event results in one message, but an SQS Event containing multiple Records, results in multiple messages published separately to the broker. \n\nThe client awaits the processing of the messages and assembles a response to be returned by the Lambda handler based on the returned values from the handler that qualified and processed the message.\n\nA sample Lambda application processing SQS events (more examples are available in [this](examples) folder)\n```typescript\n/* index.ts */\n\nimport { Context } from 'aws-lambda'\n\nimport { getLambdaMicroserviceClient } from './microservice'\n\nexport const handler = async (event: unknown, context: Context) =\u003e {\n  const client = await getLambdaMicroserviceClient()\n\n  return await client.processEvent(event, context)\n}\n```\n\n```typescript\n/* microservice.ts */\n\nimport { INestMicroservice } from '@nestjs/common'\nimport { NestFactory } from '@nestjs/core'\nimport { MicroserviceOptions } from '@nestjs/microservices'\nimport { ClientToken, LambdaMicroserviceServer } from '@klarna/nest-lambda-microservice'\n\nimport { broker } from './broker'\nimport { AppModule } from './app.module'\n\nlet microservice: INestMicroservice\nexport const getOrCreateLambdaMicroservice = async () =\u003e {\n  if (!microservice) {\n    microservice = await NestFactory.createMicroservice\u003cMicroserviceOptions\u003e(AppModule, {\n      strategy: new LambdaMicroserviceServer({ broker }),\n      logger: false,\n      abortOnError: false,\n    })\n\n    await microservice.listen()\n  }\n\n  return microservice\n}\n\nexport const getLambdaMicroserviceClient = async () =\u003e {\n  return await (await getOrCreateLambdaMicroservice()).resolve(ClientToken)\n}\n```\n\n```typescript\n/* app.module.ts */\n\nimport { Module } from '@nestjs/common'\nimport { ClientsModule } from '@nestjs/microservices'\nimport { ClientToken, LambdaMicroserviceClient } from '@klarna/nest-lambda-microservice'\nimport { APP_FILTER, APP_PIPE } from '@nestjs/core'\n\nimport { broker } from './broker'\n\nimport { BooksController } from './books.controller.ts'\nimport { BooksService } from './books.service.ts'\nimport { TransformPipe } from './transform.pipe.ts'\n\n@Module({\n  controllers: [BooksController],\n  providers: [\n    BooksService,\n    { provide: APP_PIPE, useClass: TransformPipe }\n  ],\n  imports: [\n    ClientsModule.register([{ name: ClientToken, customClass: LambdaMicroserviceClient, options: { broker } }]),\n  ],\n})\nexport class AppModule {}\n```\n\n```typescript\n/* transform.pipe.ts */\n\nimport { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'\n\n@Injectable()\nexport class TransformPipe implements PipeTransform {\n  public transform(value: any, _metadata: ArgumentMetadata) {\n    return this.tryParseJson\u003cany\u003e(value)\n  }\n\n  protected tryParseJson\u003cT\u003e(value: string): T | string {\n    try {\n      return JSON.parse(value)\n    } catch (_error: unknown) {\n      return value\n    }\n  }\n}\n```\n\n```typescript\n/* books.service.ts */\n\nimport { Injectable, Scope } from '@nestjs/common'\nimport { v4 } from 'uuid'\n\nexport interface Book {\n  id: string\n  title: string\n}\n\n@Injectable({ scope: Scope.DEFAULT })\nexport class BooksService {\n  protected books = new Map\u003cstring, Book\u003e()\n  \n  public async saveNewBook(title: string) {\n    const book = { id: v4(), title }\n\n    this.books.set(book.id, book)\n\n    return book\n  }\n}\n```\n\n```typescript\n/* create-book.dto.ts */\n\nimport { IsString } from 'class-validator'\n\nexport class CreateBookDto {\n  @IsString()\n  public title: string\n}\n```\n\n```typescript\n/* books.controller.ts */\n\nimport { Controller } from '@nestjs/common'\nimport { MessagePattern, Payload } from '@nestjs/microservices'\nimport { SqsRecordPattern, UsePartialPatternMatch } from '@klarna/nest-lambda-microservice'\n\nimport { CreateBookDto } from './create-book.dto.ts'\n\n@Controller()\n@UsePartialPatternMatch()\nexport class BooksController {\n  constructor(protected readonly booksService: BooksService) {}\n\n  @MessagePattern\u003cPartial\u003cSqsRecordPattern\u003e\u003e({ Operation: 'CreateBook' }) // Can be anything set on the SQS Record attributes\n  public async createBook(@Payload('body') sqsRecordBody: CreateBookDto) {\n    // The transform pipe parsed the serialised sqs record body\n    await this.booksService.saveNewBook(sqsRecordBody.title)\n  }\n}\n```\n\n## Pattern Matching\nTo fulfill the NestJS microservice contract, the nest-lambda-microservice transporter implements the mapping of the incoming Lambda event to the NestJS microservice message pattern based on the Lambda event source.\n\n### Full message pattern qualification\nThe message pattern is used to qualify a specific controller handler to process the event. The handler matching exactly the message pattern qualifies to process the message:\n\n```typescript\n@Controller()\nexport class Controller {\n  @MessagePattern({ action: 'foo', resourceId: '1' }) \n  public processFoo() {}\n}\n```\n\n### Partial message pattern qualification\nBy default, the Lambda microservice attempts to qualify the handler methods by performing a full match of the incoming message pattern and the handler pattern.\nTo allow partial pattern matches, one can provide the `partialMatch` option to the `MessagePattern` or mark the entire controller to use partial matches using the provided decorator.\n```typescript\n@Controller()\nexport class Controller {\n  @MessagePattern({ action: 'foo' }, { partialMatch: true }) // Applies partial match on a specific handler only\n  public processFoo() {}\n}\n```\n\n```typescript\n@UsePartialPatternMatch() // Applies partial match on all controller handlers\n@Controller()\nexport class Controller {\n  @MessagePattern({ action: 'foo' })\n  public processFoo() {}\n}\n```\n\n### Catch-all pattern\nWhen no controller qualifies the message pattern, a lookup for a \"catch-all\" handler identified by `*` pattern qualifier is performed.\nIf no such handler is defined, the message is rejected and the Lambda event processing fails.\n\n```typescript\n@Controller()\nexport class Controller {\n  @MessagePattern({ action: 'foo' }) // Qualifies messages with { action: 'foo' } patters \n  public processFoo() {}\n  \n  @MessagePattern('*') // Qualifies messages with patterns other than { action: 'foo' }\n  public processBarBazAndCo() {}\n}\n```\n\n## Message Processing\nThe Nest Lambda Microservice supports sync/async Request/Response message style (see more details on the [NestJS documentation](https://docs.nestjs.com/microservices/basics#request-response) page).\n\nThe two inputs into the Lambda function can be accessed in the NestJS application using the dependency injection:\n```typescript\nimport { Controller } from '@nestjs/common'\nimport { Ctx, MessagePattern, Payload } from '@nestjs/microservices'\nimport { LambdaContext } from '@klarna/lambda-microservice'\n\n@Controller()\nexport class Controller {\n  @MessagePattern('*') \n  public processAnyMessage(\n    @Payload() inboundMessage: unknown,\n    @Ctx() context: LambdaContext \n  ) {\n    console.log(inboundMessage) // The message as mapped from the input lambda event\n    console.log(context.getLambdaInvocationContext()) // The Lambda function context object\n  }\n}\n```\n\n### API Gateway Event\nThe incoming API Gateway Event is mapped to the message pattern using the following logic:\n\n```typescript\ninterface ApiGatewayPattern {\n  httpMethod: string\n  resource: string\n  queryStringParameters: Record\u003cstring, unknown\u003e | null\n  pathParameters: Record\u003cstring, unknown\u003e | null\n}\n```\n\nThe message payload is the original API Gateway event.\n\nFor more details see [this example](examples/api-gateway).\n\n### Custom Request Event\nThe incoming custom event is any event used to manually invoke the AWS Lambda\n\n```typescript\ntype CustomEventPattern = '*'\n```\n\nThe message payload is the original payload the Lambda was invoked with.\n\nFor more details see [this example](examples/custom).\n\n### Event Bridge Event\nThe incoming Event Bridge event is mapped to the message pattern using the following logic:\n\n```typescript\ninterface EventBridgePattern {\n  source: string\n  detailType: string    // The Event Bridge event detail-type\n  detail: JSONValue     // The Event Bridge event detail\n}\n```\n\nThe message payload is the original EventBridge event.\n\nFor more details see [this example](examples/event-bridge).\n\n### S3 Event\nThe S3 event is mapped using the following logic:\n\n```typescript\ninterface S3RecordPattern {\n  eventName: string\n  bucketName: string\n  objectKey: string\n}\n```\n\nThe message payload is a Record from the original S3 event.\n\nFor more details see [this example](examples/s3).\n\n### SNS Event\nThe SNS events are mapped using the event attributes\n\n```typescript\ninterface SnsRecordPattern {\n  [key: string]: string | number\n}\n```\n\nThe message payload is the SNSMessage.\n\nFor more details see [this example](examples/sns).\n\n### SQS Event\nThe SQS events are mapped using the event attributes\n\n```typescript\ninterface SqsRecordPattern {\n  [key: string]: string | number\n}\n```\n\nThe message payload is a Record from the original SQS event.\n\nFor more details see [this example](examples/sqs).\n\n## How to contribute\n\nSee our guide on [contributing](.github/CONTRIBUTING.md).\n\n## Release History\n\nSee our [changelog](CHANGELOG.md).\n\n## License\n\nCopyright © 2024 Klarna Bank AB\n\nFor license details, see the [LICENSE](LICENSE) file in the root of this project.\n\n\n\u003c!-- Markdown link \u0026 img dfn's --\u003e\n[ci-image]: https://img.shields.io/badge/build-passing-brightgreen?style=flat-square\n[ci-url]: https://github.com/klarna-incubator/TODO\n[license-image]: https://img.shields.io/badge/license-Apache%202-blue?style=flat-square\n[license-url]: http://www.apache.org/licenses/LICENSE-2.0\n[klarna-image]: https://img.shields.io/badge/%20-Developed%20at%20Klarna-black?style=flat-square\u0026labelColor=ffb3c7\u0026logo=klarna\u0026logoColor=black\n[klarna-url]: https://klarna.github.io\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklarna-incubator%2Fnest-lambda-microservice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fklarna-incubator%2Fnest-lambda-microservice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklarna-incubator%2Fnest-lambda-microservice/lists"}