The AWS Lambda adapter converts Hono applications into AWS Lambda handlers that work with API Gateway, ALB, Lambda Function URLs, and VPC Lattice.
Import
import {
handle,
streamHandle,
defaultIsContentTypeBinary,
getConnInfo
} from 'hono/aws-lambda'
import type {
LambdaEvent,
APIGatewayProxyResult,
ApiGatewayRequestContext,
ApiGatewayRequestContextV2,
ALBRequestContext,
LambdaContext
} from 'hono/aws-lambda'
Functions
handle()
Converts a Hono application to an AWS Lambda handler.
Accepts events from API Gateway (v1 and v2), Application Load Balancer (ALB), Lambda Function URLs, and VPC Lattice.
function handle<E extends Env, S extends Schema, BasePath extends string>(
app: Hono<E, S, BasePath>,
options?: HandleOptions
): LambdaHandler
Parameters
app - The Hono application instance
options - Optional configuration:
isContentTypeBinary - (contentType: string) => boolean - Function to determine if content should be base64 encoded
Returns
Lambda handler function compatible with API Gateway, ALB, and Function URLs.
Example
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'
const app = new Hono()
app.get('/', (c) => c.text('Hello from Lambda!'))
app.post('/api/users', async (c) => {
const body = await c.req.json()
return c.json({ success: true, data: body })
})
app.get('/image', (c) => {
// Binary responses are automatically base64 encoded
return c.body(imageBuffer, 200, {
'Content-Type': 'image/png'
})
})
export const handler = handle(app)
Custom Binary Content Detection
import { handle, defaultIsContentTypeBinary } from 'hono/aws-lambda'
export const handler = handle(app, {
isContentTypeBinary: (contentType) => {
// Use default logic
if (defaultIsContentTypeBinary(contentType)) {
return true
}
// Add custom binary types
return contentType.startsWith('image/') ||
contentType === 'application/pdf' ||
contentType === 'application/zip'
}
})
streamHandle()
Creates a streaming Lambda handler that uses response streaming for better performance with large responses.
function streamHandle<E extends Env, S extends Schema, BasePath extends string>(
app: Hono<E, S, BasePath>
): StreamingLambdaHandler
Streaming responses require Lambda function URLs or API Gateway HTTP APIs configured for streaming. This feature requires the AWS Lambda runtime to support response streaming.
Example
import { Hono } from 'hono'
import { streamHandle } from 'hono/aws-lambda'
const app = new Hono()
app.get('/large-data', async (c) => {
// Stream large responses efficiently
const stream = new ReadableStream({
start(controller) {
for (let i = 0; i < 10000; i++) {
controller.enqueue(`Line ${i}\n`)
}
controller.close()
}
})
return c.body(stream)
})
export const handler = streamHandle(app)
defaultIsContentTypeBinary()
Default function to determine if a content type should be base64 encoded.
function defaultIsContentTypeBinary(contentType: string): boolean
Returns
true if the content type is binary, false otherwise.
Logic
Returns false for:
text/* (text/plain, text/html, text/css, text/javascript, text/csv)
- Content types containing
json or xml (including application/json, application/xml, +json, +xml)
Returns true for all other content types.
getConnInfo()
Extracts connection information from AWS Lambda events.
function getConnInfo(c: Context): ConnInfo
Works with multiple event sources:
- API Gateway v1 (REST API):
requestContext.identity.sourceIp
- API Gateway v2 (HTTP API/Function URLs):
requestContext.http.sourceIp
- ALB: Falls back to
x-forwarded-for header
Returns
interface ConnInfo {
remote: {
address?: string // Client IP address
}
}
Example
import { Hono } from 'hono'
import { handle, getConnInfo } from 'hono/aws-lambda'
const app = new Hono()
app.get('/', (c) => {
const info = getConnInfo(c)
return c.text(`Your IP: ${info.remote.address}`)
})
app.get('/request-info', (c) => {
const info = getConnInfo(c)
const requestContext = c.env.requestContext
return c.json({
ip: info.remote.address,
requestId: requestContext.requestId,
stage: 'stage' in requestContext ? requestContext.stage : undefined
})
})
export const handler = handle(app)
Types
LambdaEvent
Union type of all supported Lambda event types:
type LambdaEvent =
| APIGatewayProxyEvent // API Gateway REST API (v1)
| APIGatewayProxyEventV2 // API Gateway HTTP API (v2) / Function URLs
| ALBProxyEvent // Application Load Balancer
| LatticeProxyEventV2 // VPC Lattice
APIGatewayProxyResult
Lambda response format for API Gateway:
type APIGatewayProxyResult = {
statusCode: number
statusDescription?: string
body: string
cookies?: string[] // API Gateway v2 only
isBase64Encoded: boolean
} & (WithHeaders | WithMultiValueHeaders)
Request Context Types
ApiGatewayRequestContext
API Gateway REST API (v1) request context:
interface ApiGatewayRequestContext {
accountId: string
apiId: string
domainName: string
httpMethod: string
identity: Identity
path: string
requestId: string
stage: string
// ... additional fields
}
ApiGatewayRequestContextV2
API Gateway HTTP API (v2) and Function URLs request context:
interface ApiGatewayRequestContextV2 {
accountId: string
apiId: string
domainName: string
http: {
method: string
path: string
protocol: string
sourceIp: string
userAgent: string
}
requestId: string
routeKey: string
stage: string
// ... additional fields
}
ALBRequestContext
Application Load Balancer request context:
interface ALBRequestContext {
elb: {
targetGroupArn: string
}
}
LambdaContext
AWS Lambda runtime context:
interface LambdaContext {
callbackWaitsForEmptyEventLoop: boolean
functionName: string
functionVersion: string
invokedFunctionArn: string
memoryLimitInMB: string
awsRequestId: string
logGroupName: string
logStreamName: string
identity?: CognitoIdentity
clientContext?: ClientContext
getRemainingTimeInMillis(): number
}
Accessing Lambda Context
The Lambda event and context are available through c.env:
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'
import type { LambdaEvent, LambdaContext } from 'hono/aws-lambda'
type Bindings = {
event: LambdaEvent
requestContext: ApiGatewayRequestContextV2
lambdaContext: LambdaContext
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/lambda-info', (c) => {
const { lambdaContext } = c.env
return c.json({
functionName: lambdaContext.functionName,
requestId: lambdaContext.awsRequestId,
remainingTime: lambdaContext.getRemainingTimeInMillis(),
memoryLimit: lambdaContext.memoryLimitInMB
})
})
export const handler = handle(app)
Event Sources
The adapter automatically detects and handles:
- API Gateway REST API (v1): Traditional REST APIs with resource-based routing
- API Gateway HTTP API (v2): Lower latency, lower cost HTTP APIs
- Lambda Function URLs: Direct HTTPS endpoints for Lambda functions
- Application Load Balancer: ALB target integrations
- VPC Lattice: Service mesh integrations
Binary Content
Binary responses are automatically base64 encoded based on:
- Content-Type header (via
isContentTypeBinary option)
- Content-Encoding header (gzip, deflate, compress, br)
- Single-value headers: Used by default and API Gateway v2
- Multi-value headers: Used when the event includes
multiValueHeaders
Cookies
- API Gateway v2: Uses the
cookies array in the response
- API Gateway v1: Uses
multiValueHeaders['set-cookie']
- ALB: Depends on multi-value headers configuration
Deployment
Using AWS SAM
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HonoFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs20.x
Events:
ApiEvent:
Type: HttpApi
Properties:
Path: /{proxy+}
Method: ANY
Using AWS CDK
import * as lambda from 'aws-cdk-lib/aws-lambda'
import * as apigateway from 'aws-cdk-lib/aws-apigatewayv2'
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'
const handler = new lambda.Function(this, 'HonoHandler', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('dist'),
handler: 'index.handler',
})
const httpApi = new apigateway.HttpApi(this, 'HonoApi', {
defaultIntegration: new HttpLambdaIntegration('HonoIntegration', handler),
})
Using Serverless Framework
# serverless.yml
service: hono-lambda
provider:
name: aws
runtime: nodejs20.x
functions:
api:
handler: index.handler
events:
- httpApi:
path: /{proxy+}
method: ANY
See Also