---
title: Serverless Functions
description: Deploy serverless functions using AWS Lambda and API Gateway
---
import { Icon } from 'astro-icon/components';
import ServerlessAPIArchitecture from '@/components/docs/patterns/ServerlessAPIArchitecture.astro';
Deploy serverless APIs and backend functions on AWS Lambda with modern web frameworks like Express.js, Hono, NestJS, and Fastify.
Thunder provides the [@thunderso/cdk-functions](https://github.com/thunder-so/cdk-functions) package for deploying Lambda functions with API Gateway, supporting both standard zip deployments and container images for custom runtimes.
## Supported Frameworks
- [Hono](https://hono.dev/)
- [NestJS](https://nestjs.com/)
- [Fastify](https://www.fastify.io/)
- [Koa](https://koajs.com/)
- [AdonisJS](https://adonisjs.com/)
- [Sails.js](https://sailsjs.com/)
- [LoopBack](https://loopback.io/)
- [Feathers](https://feathersjs.com/)
- [Restify](http://restify.com/)
- Any web application framework
## Serverless API Architecture
The serverless architecture provides scalable, event-driven compute for APIs without managing servers.
## Zip Deployment Pipeline
The zip deployment pipeline packages and deploys lightweight Lambda functions for standard use cases.
**GitHub** triggers deployments on code changes. **CodePipeline** orchestrates the workflow while **CodeBuild** packages the function code into a zip file and deploys directly to **Lambda**.
## Container Deployment Pipeline
The container deployment pipeline builds custom runtime environments for advanced use cases and larger dependencies.
**GitHub** triggers deployments. **CodeBuild** builds Docker images with custom runtimes, pushes to **ECR**, then deploys container images to **Lambda** for advanced use cases requiring custom dependencies or alternative runtimes like Bun.
## Quick Start
Get your serverless API deployed to AWS Lambda in minutes. This guide covers installation, basic configuration, and deployment.
### Installation
```bash
bun add -D tsx @thunderso/cdk-functions
```
### Basic Setup
```bash
mkdir stack && touch stack/index.ts
```
### Configuration
```ts
// stack/index.ts
import { Cdk, FunctionStack, type FunctionProps } from '@thunderso/cdk-functions';
const fnProps: FunctionProps = {
env: {
account: 'your-account-id',
region: 'us-east-1',
},
application: 'my-api',
service: 'backend',
environment: 'production',
functionProps: {
codeDir: 'dist/',
handler: 'index.handler',
},
};
new FunctionStack(
new Cdk.App(),
`${fnProps.application}-${fnProps.service}-${fnProps.environment}-stack`,
fnProps
);
```
### Deploy
```bash
bunx cdk deploy --all --app="bunx tsx stack/index.ts"
```
## Custom Domain Setup
Connect your API to a custom domain using Route 53 and ACM certificates. The certificate must be issued in the same region as your Lambda function.
```ts
const fnProps: FunctionProps = {
// ... other props
domain: 'api.example.com',
hostedZoneId: 'Z1D633PJN98FT9',
regionalCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/abcd1234-abcd-1234-abcd-1234abcd1234',
};
```
## Advanced Configuration
### Lambda Settings
Fine-tune your function's performance with runtime selection, memory allocation, timeout configuration, and ARM64 architecture support for better price-performance.
```ts
import { Runtime, Architecture } from 'aws-cdk-lib/aws-lambda';
const fnProps: FunctionProps = {
// ... other props
functionProps: {
runtime: Runtime.NODEJS_20_X,
architecture: Architecture.ARM_64,
memorySize: 1792,
timeout: 10,
tracing: true,
keepWarm: true,
},
};
```
### Environment Variables
Manage configuration with plain environment variables and secure secrets from AWS Secrets Manager. The library automatically grants Lambda permissions to read specified secrets.
```ts
const fnProps: FunctionProps = {
// ... other props
functionProps: {
variables: [
{ API_URL: 'https://api.example.com' },
{ NODE_ENV: 'production' }
],
secrets: [
{
key: 'DATABASE_URL',
resource: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:db-url-abc123'
}
],
}
};
```
## Container Deployments
Deploy Lambda functions as container images to use custom runtimes, package large dependencies, or run alternative runtimes like Bun. Container images support up to 10GB compared to the 250MB zip limit.
### Node.js Container
Use the official AWS Lambda Node.js base image for standard Node.js deployments with custom dependencies or build processes.
```dockerfile
# Dockerfile.node
FROM public.ecr.aws/lambda/nodejs:22 AS base
WORKDIR ${LAMBDA_TASK_ROOT}
COPY . .
RUN bun install --production
RUN bun run build
FROM public.ecr.aws/lambda/nodejs:22
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=base /var/task/dist/* ./
COPY --from=base /var/task/node_modules node_modules
CMD [ "index.handler" ]
```
```ts
const fnProps: FunctionProps = {
// ... other props
functionProps: {
dockerFile: 'Dockerfile.node',
},
};
```
### Bun Runtime Container
Deploy Lambda functions using the Bun runtime for faster cold starts and improved performance. Requires a fetch-compatible handler that matches the Fetch API standard.
```dockerfile
# Dockerfile.bun
FROM oven/bun:latest AS base
WORKDIR /tmp
COPY . .
RUN bun install
RUN bun run build
FROM public.ecr.aws/lambda/provided:al2023
WORKDIR ${LAMBDA_TASK_ROOT}
COPY --from=base /tmp/dist/* ./
COPY --from=base /tmp/node_modules node_modules
CMD [ "lambda-bun.fetch" ]
```
```ts
const fnProps: FunctionProps = {
// ... other props
functionProps: {
dockerFile: 'Dockerfile.bun',
},
};
```