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:
Basic Usage
Create your application and wrap it with the Lambda handler:
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:
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:
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:
Lambda Function URLs
Create deployment package
zip -r function.zip dist node_modules
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
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:
{
"compilerOptions" : {
"target" : "ES2022" ,
"module" : "ES2022" ,
"moduleResolution" : "bundler" ,
"outDir" : "./dist" ,
"esModuleInterop" : true ,
"skipLibCheck" : true
}
}
{
"scripts" : {
"build" : "tsc" ,
"deploy" : "sam build && sam deploy"
}
}
Best Practices
Lambda has size limits. Minimize dependencies and use tree-shaking.
Use provisioned concurrency for latency-sensitive apps
Reduce cold starts with provisioned concurrency.
Add a /health endpoint for monitoring.
Use environment variables for configuration
Store API keys and configuration in environment variables.
Use AWS X-Ray for debugging and performance analysis.
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