Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,126 @@ When you execute your Fastify application like always,
i.e. `node app.js` *(the detection for this could be `require.main === module`)*,
you can normally listen to your port, so you can still run your Fastify function locally.

## Usage with NestJS

### main.ts

```typescript
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import awsLambdaFastify, { PromiseHandler } from '@fastify/aws-lambda';
import fastify, { FastifyInstance, FastifyServerOptions } from 'fastify';
import { Context, APIGatewayProxyEvent } from 'aws-lambda';
import { Logger } from '@nestjs/common';

interface NestApp {
app: NestFastifyApplication;
instance: FastifyInstance;
}

let cachedNestApp;

async function bootstrapServer(): Promise {
Comment on lines +102 to +104
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable cachedNestApp is missing a type annotation. It should be typed to match what awsLambdaFastify returns. Consider adding a type annotation such as let cachedNestApp: PromiseHandler | undefined; or let cachedNestApp: any; for clarity.

Suggested change
let cachedNestApp;
async function bootstrapServer(): Promise {
let cachedNestApp: PromiseHandler | undefined;
async function bootstrapServer(): Promise<NestApp> {

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function bootstrapServer is missing the generic type parameter for its Promise return type. The return type should be Promise<NestApp> instead of just Promise.

Suggested change
async function bootstrapServer(): Promise {
async function bootstrapServer(): Promise<NestApp> {

Copilot uses AI. Check for mistakes.

const serverOptions: FastifyServerOptions = {
logger: (process.env.LOGGER || '0') == '1',
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using == for comparison is not recommended in TypeScript/JavaScript. Use strict equality === instead: (process.env.LOGGER || '0') === '1'.

Suggested change
logger: (process.env.LOGGER || '0') == '1',
logger: (process.env.LOGGER || '0') === '1',

Copilot uses AI. Check for mistakes.
};
const instance: FastifyInstance = fastify(serverOptions);
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(instance),
{
logger: !process.env.AWS_EXECUTION_ENV ? new Logger() : console,
},
);

const CORS_OPTIONS = {
origin: '*',
allowedHeaders: '*',
exposedHeaders: '*',
credentials: false,
methods: ['GET', 'PUT', 'OPTIONS', 'POST', 'DELETE'],
};

app.register(require('fastify-cors'), CORS_OPTIONS);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package fastify-cors has been deprecated and replaced with @fastify/cors. The code should use the newer package instead. Update the line to use @fastify/cors and consider importing it at the top of the file rather than using require() inline, which would be more consistent with the TypeScript imports used elsewhere in the example.

Copilot uses AI. Check for mistakes.

app.setGlobalPrefix(process.env.API_PREFIX);

await app.init();

return {
app,
instance
};
}

export const handler = async (
event: APIGatewayProxyEvent,
context: Context,
): Promise<PromiseHandler> => {
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type Promise<PromiseHandler> appears to be incorrect. The PromiseHandler type from @fastify/aws-lambda represents the handler function type, not the return value of the handler. The handler should return the actual response from the lambda proxy, which is typically something like Promise<APIGatewayProxyResult>. Consider removing the explicit return type or using the correct return type.

Suggested change
): Promise<PromiseHandler> => {
) => {

Copilot uses AI. Check for mistakes.
if (!cachedNestApp) {
const nestApp = await bootstrap();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function being called is bootstrap() but the function defined above is named bootstrapServer(). This is a critical bug that would prevent the code from working. The call should be changed to bootstrapServer().

Suggested change
const nestApp = await bootstrap();
const nestApp = await bootstrapServer();

Copilot uses AI. Check for mistakes.
cachedNestApp = awsLambdaFastify(nestApp.instance, {
decorateRequest: true,
});
}

return cachedNestApp(event, context);
};
```

Notice we are caching the initialized app. In a lambda environment, the handler will be called on each new request. Anything outside the handler may be cached between calls, which lasts as long as AWS has kept the same lambda execution environment up for your function. By storing the initialized app as a variable, we can minimize the cold-start time of our app since it will be constructed once per execution environment spin up.

## Usage with NestJS/GraphQL
In addition to the above, when using NestJS with GraphQL in a lambda environment, you will need to copy your `schema.gql` into your `dist` folder rather than relying on the `autoSchemaFile` option since this tries to write to `/src` directory inside a running lambda function and you are only allowed to write to `/tmp` directory. You can modify your build script in your `package.json` to acheive this:
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a spelling error: "acheive" should be "achieve".

Suggested change
In addition to the above, when using NestJS with GraphQL in a lambda environment, you will need to copy your `schema.gql` into your `dist` folder rather than relying on the `autoSchemaFile` option since this tries to write to `/src` directory inside a running lambda function and you are only allowed to write to `/tmp` directory. You can modify your build script in your `package.json` to acheive this:
In addition to the above, when using NestJS with GraphQL in a lambda environment, you will need to copy your `schema.gql` into your `dist` folder rather than relying on the `autoSchemaFile` option since this tries to write to `/src` directory inside a running lambda function and you are only allowed to write to `/tmp` directory. You can modify your build script in your `package.json` to achieve this:

Copilot uses AI. Check for mistakes.

```js
"build": "nest build && yarn copyschema",
"copyschema": "cp src/schema.gql dist/schema.gql"
```

You will also need to modify your `app.module.ts` file:

### app.module.ts
```typescript
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app.module.ts example is missing necessary import statements. At minimum, it should include imports for Module, GraphQLModule, MercuriusDriverConfig, GqlModuleOptions, MercuriusDriver, join, and any other referenced symbols like createXYZLoader, XYZService, XYZModule, AppController, and AppService. Without these imports, the code example cannot be used as-is.

Suggested change
```typescript
```typescript
import { Module } from '@nestjs/common';
import { GraphQLModule, GqlModuleOptions } from '@nestjs/graphql';
import { MercuriusDriver, MercuriusDriverConfig } from '@nestjs/mercurius';
import { join } from 'path';
import { createXYZLoader } from './xyz.loader';
import { XYZService } from './xyz.service';
import { XYZModule } from './xyz.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';

Copilot uses AI. Check for mistakes.
@Module({
imports: [
GraphQLModule.forRootAsync<MercuriusDriverConfig>({
imports: [XYZModule],
useFactory: () => {
const schemaModuleOptions: Partial<GqlModuleOptions> = {};

if (process.env.NODE_ENV !== 'production' || process.env.IS_OFFLINE) {
schemaModuleOptions.autoSchemaFile = join(
process.cwd(),
'src/schema.gql',
);
} else {
schemaModuleOptions.typePaths = ['dist/*.gql'];
}

return {
graphiql: true,
context: (req: any) => ({
XYZLoader: createXYZLoader(XYZService),
headers: req.headers,
}),
...schemaModuleOptions,
};
},
driver: MercuriusDriver,
}),
XYZModule,
],
controllers: [AppController],
providers: [AppService],
})
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code example is incomplete and missing the class decorator and export. The example should start with export class AppModule {} to be a complete and valid TypeScript class definition.

Suggested change
})
})
export class AppModule {}

Copilot uses AI. Check for mistakes.
```

### 📣Hint

#### Lambda arguments
Expand Down