Skip to main content
AWS Lambda is a serverless compute service that runs your code in response to events. Hono provides a robust adapter for AWS Lambda with support for API Gateway, ALB, and Lambda Function URLs.

Quick Start

Create a new Hono project for AWS Lambda:
npm create hono@latest my-app
Select “aws-lambda” as your template when prompted.

Installation

Add Hono to your existing AWS Lambda project:
npm install hono

Basic Usage

Create your application and wrap it with the Lambda handler:
index.ts
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()

app.get('/', (c) => c.text('Hello AWS Lambda!'))

app.get('/api/hello', (c) => {
  return c.json({ message: 'Hello from Lambda!' })
})

export const handler = handle(app)
The handle adapter converts your Hono app into an AWS Lambda handler that works with API Gateway v1, API Gateway v2, ALB, and Lambda Function URLs.

Event Sources

The Hono adapter automatically detects and handles different event sources:

API Gateway v1 (REST API)

import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id })
})

export const handler = handle(app)

API Gateway v2 (HTTP API)

import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()
app.post('/api/data', async (c) => {
  const body = await c.req.json()
  return c.json({ received: body })
})

export const handler = handle(app)

Application Load Balancer (ALB)

The adapter handles ALB events with multi-value headers:
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()
app.get('/health', (c) => c.text('OK'))

export const handler = handle(app)

Lambda Function URLs

import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()
app.get('/', (c) => c.text('Hello from Function URL!'))

export const handler = handle(app)

Streaming Responses

For Lambda Response Streaming (Node.js 20+):
import { Hono } from 'hono'
import { streamHandle } from 'hono/aws-lambda'
import { stream } from 'hono/streaming'

const app = new Hono()

app.get('/stream', (c) => {
  return stream(c, async (stream) => {
    for (let i = 0; i < 10; i++) {
      await stream.writeln(`Chunk ${i}`)
      await stream.sleep(100)
    }
  })
})

export const handler = streamHandle(app)
Streaming requires Lambda Response Streaming to be enabled in your function configuration.

Accessing Lambda Context

Access the Lambda event and context:
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'
import type { LambdaEvent, LambdaContext } from 'hono/aws-lambda'

type Bindings = {
  event: LambdaEvent
  lambdaContext: LambdaContext
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/info', (c) => {
  const event = c.env.event
  const lambdaContext = c.env.lambdaContext
  
  return c.json({
    requestId: lambdaContext.awsRequestId,
    functionName: lambdaContext.functionName,
    sourceIp: event.requestContext.identity?.sourceIp,
  })
})

export const handler = handle(app)

Connection Info

Get connection information:
import { Hono } from 'hono'
import { handle, getConnInfo } from 'hono/aws-lambda'

const app = new Hono()

app.get('/conninfo', (c) => {
  const info = getConnInfo(c)
  return c.json({
    remote: info.remote,
  })
})

export const handler = handle(app)

Binary Content

Handle binary responses (images, PDFs, etc.):
import { Hono } from 'hono'
import { handle, defaultIsContentTypeBinary } from 'hono/aws-lambda'

const app = new Hono()

app.get('/image', (c) => {
  // Return binary content
  return c.body(imageBuffer, 200, {
    'Content-Type': 'image/png',
  })
})

export const handler = handle(app, {
  isContentTypeBinary: (contentType) => {
    // Use default + custom logic
    if (defaultIsContentTypeBinary(contentType)) {
      return true
    }
    return contentType.startsWith('image/') || contentType === 'application/pdf'
  },
})

Environment Variables

Access Lambda environment variables:
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()

app.get('/config', (c) => {
  return c.json({
    region: process.env.AWS_REGION,
    apiKey: process.env.API_KEY,
  })
})

export const handler = handle(app)

Deployment

AWS SAM

Create a template.yaml:
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  HonoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: dist/index.handler
      Runtime: nodejs20.x
      Timeout: 30
      MemorySize: 512
      Events:
        ApiEvent:
          Type: HttpApi
          Properties:
            Path: /{proxy+}
            Method: ANY
Deploy:
sam build
sam deploy --guided

AWS CDK

Create a Lambda function with CDK:
import * as cdk from 'aws-cdk-lib'
import * as lambda from 'aws-cdk-lib/aws-lambda'
import * as apigateway from 'aws-cdk-lib/aws-apigatewayv2'
import * as integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations'

const fn = new lambda.Function(this, 'HonoFunction', {
  runtime: lambda.Runtime.NODEJS_20_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('dist'),
})

const httpApi = new apigateway.HttpApi(this, 'HttpApi', {
  defaultIntegration: new integrations.HttpLambdaIntegration('Integration', fn),
})

Serverless Framework

Create a serverless.yml:
serverless.yml
service: hono-lambda

provider:
  name: aws
  runtime: nodejs20.x
  region: us-east-1

functions:
  api:
    handler: dist/index.handler
    events:
      - httpApi:
          path: /{proxy+}
          method: '*'
Deploy:
serverless deploy

Lambda Function URLs

1

Build your function

npm run build
2

Create deployment package

zip -r function.zip dist node_modules
3

Deploy to Lambda

aws lambda create-function \
  --function-name my-hono-app \
  --runtime nodejs20.x \
  --handler dist/index.handler \
  --zip-file fileb://function.zip \
  --role arn:aws:iam::ACCOUNT:role/lambda-role
4

Create Function URL

aws lambda create-function-url-config \
  --function-name my-hono-app \
  --auth-type NONE

Project Structure

my-lambda-app/
├── src/
│   └── index.ts
├── dist/
├── package.json
├── tsconfig.json
└── template.yaml (or serverless.yml)

Build Configuration

Optimize your build for Lambda:
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "outDir": "./dist",
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
package.json
{
  "scripts": {
    "build": "tsc",
    "deploy": "sam build && sam deploy"
  }
}

Best Practices

Lambda has size limits. Minimize dependencies and use tree-shaking.
Reduce cold starts with provisioned concurrency.
Add a /health endpoint for monitoring.
Store API keys and configuration in environment variables.
Use AWS X-Ray for debugging and performance analysis.

Performance Tips

  • Use Node.js 20+ for best performance
  • Enable arm64 architecture for better price/performance
  • Optimize memory allocation (more memory = more CPU)
  • Use Lambda Layers for shared dependencies
  • Implement connection pooling for databases

Resources

AWS Lambda Docs

Official AWS Lambda documentation

API Gateway

Learn about API Gateway integration

Build docs developers (and LLMs) love