Skip to content

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*Handler factories -- 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:

typescript
// 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:

typescript
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:

typescript
// 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 default arm64)
  • 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:

FeatureCloudFront FunctionsLambda@Edge
RuntimeJavaScript (ES 5.1)Node.js 24
Execution time< 1 ms< 5 s (viewer) / < 30 s (origin)
Memory2 MB128 MB (viewer) / 10 GB (origin)
Network accessNoYes
Cost~1/6 of Lambda@EdgeHigher
Use casesURL rewrites, header manipulation, redirectsAuth, 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 except observability/edge-logging
  • [ ] No @aws-lambda-powertools/* imports
  • [ ] No define*Handler factory or withObservability wrapper
  • [ ] Bare export const handler only
  • [ ] defineLambda({ edge: true }) declared
  • [ ] Bundle size < 5 KB (check with mantle check bundles)
  • [ ] Uses createEdgeLogger for logging, not console.log