adapter-aws-lambda

>

trpc/trpc31 installsMITSynced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: adapter-aws-lambda
description: >
license: MIT
---

# tRPC — Adapter: AWS Lambda

## Setup

```ts
// server.ts
import { initTRPC } from '@trpc/server';
import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda';
import { awsLambdaRequestHandler } from '@trpc/server/adapters/aws-lambda';
import type { APIGatewayProxyEventV2 } from 'aws-lambda';
import { z } from 'zod';

const t = initTRPC.create();

const appRouter = t.router({
  greet: t.procedure
    .input(z.object({ name: z.string() }))
    .query(({ input }) => ({ greeting: `Hello, ${input.name}!` })),
});

export type AppRouter = typeof appRouter;

const createContext = ({
  event,
  context,
}: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) => ({
  event,
  lambdaContext: context,
});

export const handler = awsLambdaRequestHandler({
  router: appRouter,
  createContext,
});
```

## Core Patterns

### API Gateway v1 (REST) handler

```ts
import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda';
import { awsLambdaRequestHandler } from '@trpc/server/adapters/aws-lambda';
import type { APIGatewayProxyEvent } from 'aws-lambda';
import { appRouter } from './router';

const createContext = ({
  event,
  context,
}: CreateAWSLambdaContextOptions<APIGatewayProxyEvent>) => ({
  user: event.requestContext.authorizer?.claims,
});

export const handler = awsLambdaRequestHandler({
  router: appRouter,
  createContext,
});
```

Use `APIGatewayProxyEvent` for REST API (v1 payload format) and `APIGatewayProxyEventV2` for HTTP API (v2 payload format).

### Response streaming with awsLambdaStreamingRequestHandler

```ts
/// <reference types="aws-lambda" />
import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda';
import { awsLambdaStreamingRequestHandler } from '@trpc/server/adapters/aws-lambda';
import type { APIGatewayProxyEventV2 } from 'aws-lambda';
import { appRouter } from './router';

const createContext = ({
  event,
  context,
}: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) => ({});

export const handler = awslambda.streamifyResponse(
  awsLambdaStreamingRequestHandler({
    router: appRouter,
    createContext,
  }),
);
```

Response streaming is supported for Lambda Function URLs and API Gateway REST APIs (with `responseTransferMode: STREAM`). The `awslambda` namespace is provided by the Lambda execution environment.

### Streaming async generator procedure

```ts
import { initTRPC } from '@trpc/server';

const t = initTRPC.create();

export const appRouter = t.router({
  countdown: t.procedure.query(async function* () {
    for (let i = 10; i >= 0; i--) {
      await new Promise((resolve) => setTimeout(resolve, 500));
      yield i;
    }
  }),
});
```

Pair with `httpBatchStreamLink` on the client for streamed responses.

### Limiting batch size with maxBatchSize

```ts
import { awsLambdaRequestHandler } from '@trpc/server/adapters/aws-lambda';
import { appRouter } from './router';

export const handler = awsLambdaRequestHandler({
  router: appRouter,
  createContext,
  maxBatchSize: 10,
});
```

Requests batching more than `maxBatchSize` operations are rejected with a `400 Bad Request` error. Set `maxItems` on your client's `httpBatchLink` to the same value to avoid exceeding the limit.

## Common Mistakes

### HIGH Using httpBatchLink with per-procedure API Gateway resources

Wrong:

```ts
// API Gateway has a separate resource for each procedure
// e.g., /getUser, /createUser
// Client uses:
import { httpBatchLink } from '@trpc/client';

httpBatchLink({ url: 'https://api.example.com' });
// Batch request to /getUser,createUser → 404
```

Correct:

```ts
import { httpBatchLink, httpLink } from '@trpc/client';

// Option A: Single catch-all resource (e.g., /{proxy+})
httpBatchLink({ url: 'https://api.example.com' });

// Option B: Per-procedure resources with httpLink (no batching)
httpLink({ url: 'https://api.example.com' });
```

`httpBatchLink` sends multiple procedure names in the URL path (e.g., `getUser,createUser`). If API Gateway routes are per-procedure, the combined path does not match any resource and returns 404. Use a single catch-all resource or switch to `httpLink`.

Source: www/docs/server/adapters/aws-lambda.md

### HIGH Forgetting streamifyResponse wrapper for streaming

Wrong:

```ts
export const handler = awsLambdaStreamingRequestHandler({
  router: appRouter,
  createContext,
});
```

Correct:

```ts
export const handler = awslambda.streamifyResponse(
  awsLambdaStreamingRequestHandler({
    router: appRouter,
    createContext,
  }),
);
```

`awsLambdaStreamingRequestHandler` requires wrapping with `awslambda.streamifyResponse()` to enable Lambda response streaming. Without it, Lambda treats the handler as a standard buffered response.

Source: www/docs/server/adapters/aws-lambda.md

## See Also

- **server-setup** -- `initTRPC.create()`, router/procedure definition, context
- **adapter-fetch** -- alternative for edge/serverless runtimes using Fetch API
- **links** -- `httpBatchLink` vs `httpLink` for API Gateway routing considerations
- AWS Lambda docs: https://docs.aws.amazon.com/lambda/latest/dg/welcome.html

More DevOps & Infrastructure skills

← All DevOps & Infrastructure skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY