Lambda@Edge
Lambda@Edge functions run at CloudFront edge locations, close to end users. They have strict constraints that differ from standard Lambda functions.
Constraints
Lambda@Edge functions are subject to hard limits that standard Lambdas do not have:
- No environment variables -- CloudFront does not inject env vars at the edge
- No Lambda Layers -- layers are not available in edge replicas
- x86_64 only -- ARM/Graviton is not supported at edge locations
- Bundle size < 5 KB -- viewer-request/response functions have a 1 MB limit, but keeping bundles under 5 KB ensures fast cold starts
- No
define*Handlerfactories -- the observability middleware and Powertools dependencies are too large - No
@mantleframework/*imports (except@mantleframework/observability/edge-logging) -- framework packages pull in dependencies that exceed the bundle budget - Bare
export const handler-- no wrapper functions
Handler Pattern
A Lambda@Edge handler is a plain function export with no framework wrapping:
// src/lambdas/edge/SecurityHeaders/index.ts
import type { CloudFrontRequestEvent, CloudFrontResponseResult } from 'aws-lambda'
import { createEdgeLogger } from '@mantleframework/observability/edge-logging'
const logger = createEdgeLogger({ service: 'SecurityHeaders' })
export const handler = async (event: CloudFrontRequestEvent): Promise<CloudFrontResponseResult> => {
const request = event.Records[0]!.cf.request
logger.info('Processing request', { uri: request.uri })
const response = event.Records[0]!.cf.response
if (!response) {
return request
}
response.headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubdomains; preload'
}]
response.headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff'
}]
logger.logOutgoingFixture(response)
return response
}Edge Logging
Standard @mantleframework/observability imports (Powertools Logger, OpenTelemetry) are not available at the edge. Use createEdgeLogger from @mantleframework/observability/edge-logging instead:
import { createEdgeLogger } from '@mantleframework/observability/edge-logging'
const logger = createEdgeLogger({
service: 'MyEdgeFunction',
version: '1.0.0',
defaultLevel: 'INFO',
persistentAttributes: { distribution: 'E1234567890' }
})
logger.debug('Verbose detail', { uri: '/path' })
logger.info('Request processed', { status: 200 })
logger.warn('Unexpected header', { header: 'X-Custom' })
logger.error('Failed to process', { error: 'timeout' })The edge logger is zero-dependency -- it writes structured JSON via console methods, which Lambda's Advanced Logging Controls captures.
Infrastructure
Use defineLambda with edge: true to declare a Lambda@Edge function:
// src/lambdas/edge/SecurityHeaders/index.ts
import { defineLambda } from '@mantleframework/core'
defineLambda({ edge: true })The CLI generates the correct Terraform configuration:
architecture = "x86_64"(overrides the defaultarm64)publish = true(required for Lambda@Edge versioning)- Edge-compatible IAM assume role policy (
edgelambda.amazonaws.com) - Deployed to
us-east-1(required by CloudFront) - No ADOT layer (automatically skipped)
CloudFront Functions Alternative
For simple request/response transformations that do not need network access or a full runtime, prefer CloudFront Functions over Lambda@Edge:
| Feature | CloudFront Functions | Lambda@Edge |
|---|---|---|
| Runtime | JavaScript (ES 5.1) | Node.js 24 |
| Execution time | < 1 ms | < 5 s (viewer) / < 30 s (origin) |
| Memory | 2 MB | 128 MB (viewer) / 10 GB (origin) |
| Network access | No | Yes |
| Cost | ~1/6 of Lambda@Edge | Higher |
| Use cases | URL rewrites, header manipulation, redirects | Auth, A/B testing, dynamic content |
CloudFront Functions are defined directly in Terraform, not as Lambda handlers. They are appropriate when you need:
- Simple header additions or removals
- URL rewrites or redirects
- Cache key normalization
- Request/response transformations without external calls
Checklist
Before deploying a Lambda@Edge function, verify:
- [ ] No
@mantleframework/*imports exceptobservability/edge-logging - [ ] No
@aws-lambda-powertools/*imports - [ ] No
define*Handlerfactory orwithObservabilitywrapper - [ ] Bare
export const handleronly - [ ]
defineLambda({ edge: true })declared - [ ] Bundle size < 5 KB (check with
mantle check bundles) - [ ] Uses
createEdgeLoggerfor logging, notconsole.log