GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • oRPC
  • Documentation
  • Blog
  • Comparison
  • From V1
  • Sponsors
  • Experts
  • Releases
  • Discussions
  • LLM Context
  • LLM Context (Full)
  • V1 Documentation
  • Contract-First
  • Requirements

This view

  • Original page
  • New address

GeezerVison is showing orpc.dev — AWS Lambda Adapter - oRPC

On this page
  • Server Usage
  • Event Stream Options

AWS Lambda Adapter

Use oRPC on AWS Lambda behind API Gateway (payload formats 1.0 and 2.0) and Lambda Function URLs using response streaming.

This adapter requires the Lambda Node.js runtime with response streaming enabled, so handlers must be wrapped with awslambda.streamifyResponse.

Sponsors

ScreenshotOne.comThe screenshot API for developersYuzuWe're hiring NYC based engineersMisskeyHQDecentralized microblogging SNS born on Earth

Server Usage

import type { APIGatewayProxyEventV2, AwsLambdaGlobal } from '@orpc/server/aws-lambda'
import { onError } from '@orpc/server'
import { RPCHandler } from '@orpc/server/aws-lambda'
import { CORSHandlerPlugin } from '@orpc/server/plugins'

declare const awslambda: AwsLambdaGlobal

const handler = new RPCHandler(router, {
  plugins: [new CORSHandlerPlugin()],
  interceptors: [
    onError((error) => {
      console.error(error)
    }),
  ],
})

export const rpc = awslambda.streamifyResponse<APIGatewayProxyEventV2>(
  async (event, responseStream, context) => {
    const { matched } = await handler.handle(event, responseStream, {
      prefix: '/rpc',
      context: {}, // Provide initial context if needed, can be an async function
    })

    if (matched) {
      return
    }

    awslambda.HttpResponseStream.from(responseStream, {
      statusCode: 404,
      headers: {},
      cookies: [],
    }).end('Not found')
  },
)
import type { APIGatewayProxyEventV2, AwsLambdaGlobal } from '@orpc/openapi/aws-lambda'
import { OpenAPIHandler } from '@orpc/openapi/aws-lambda'
import { onError } from '@orpc/server'
import { CORSHandlerPlugin } from '@orpc/server/plugins'

declare const awslambda: AwsLambdaGlobal

const handler = new OpenAPIHandler(router, {
  plugins: [new CORSHandlerPlugin()],
  interceptors: [
    onError((error) => {
      console.error(error)
    }),
  ],
})

export const api = awslambda.streamifyResponse<APIGatewayProxyEventV2>(
  async (event, responseStream, context) => {
    const { matched } = await handler.handle(event, responseStream, {
      prefix: '/api',
      context: {}, // Provide initial context if needed, can be an async function
    })

    if (matched) {
      return
    }

    awslambda.HttpResponseStream.from(responseStream, {
      statusCode: 404,
      headers: {},
      cookies: [],
    }).end('Not found')
  },
)

To better support Blob, File, and ReadableStream<Uint8Array> at the root level in cross-origin scenarios, extend your CORS allowlist to allow clients to read the Content-Disposition and Standard-Server response headers. Learn more in the Standard Server documentation. If you use the CORS Plugin, include them in exposeHeaders:

const cors = new CORSHandlerPlugin({
  exposeHeaders: ['Content-Disposition', 'Standard-Server'],
})

Event Stream Options

You can configure how an AsyncIteratorObject is streamed to the client using the sendStandardResponse.eventStream options when creating the handler.

const handler = new OpenAPIHandler(router, {
  sendStandardResponse: {
    eventStream: {
      /**
       * Initial comment sent immediately upon stream start to flush headers. This allows the
       * receiving side to establish the connection without waiting for the first event.
       *
       * `false` disables it, an object customizes it.
       *
       * @default true
       */
      initialComment: {
        /**
         * The content of the initial comment sent upon stream start. Must not include newline characters.
         *
         * @default ''
         */
        comment: '',
      },
      /**
       * Ping comment sent periodically to keep the connection alive.
       *
       * `false` disables it, an object customizes it.
       *
       * @default true
       */
      keepAlive: {
        /**
         * Interval (in milliseconds) between ping comments sent after the last event.
         *
         * @default 15000
         */
        interval: 15000,
        /**
         * The content of the ping comment. Must not include newline characters.
         *
         * @default ''
         */
        comment: '',
      },
    },
  },
})

Sponsors

ScreenshotOne.comThe screenshot API for developersYuzuWe're hiring NYC based engineers

Last updated on November 9, 2026

Was this page helpful?

Thanks for your feedback!

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.