[lambda] Support for Managed EC2 Instances

I'm excited to share that the Swift AWS Lambda Runtime now supports AWS Lambda Managed Instances, a new deployment model that combines EC2 flexibility with serverless simplicity.

What are Lambda Managed Instances?

Lambda Managed Instances enable you to run Lambda functions on your current-generation Amazon EC2 instances while AWS handles all infrastructure management (instance lifecycle, patching, routing, load balancing, auto-scaling). The key difference from traditional Lambda is concurrent execution support—multiple invocations can run simultaneously within the same execution environment.

This is particularly useful for:

  • Sustained workloads where EC2 pricing models provide cost optimization
  • Specialized compute requirements (Graviton4, network-optimized instances)
  • High-throughput scenarios benefiting from concurrent execution
  • Workloads needing EC2 flexibility without operational overhead

Code Changes

Migrating existing Lambda functions requires just two changes:

1. Replace LambdaRuntime with LambdaManagedRuntime:

// Before
let runtime = LambdaRuntime {
    (event: HelloRequest, context: LambdaContext) in
    HelloResponse(greetings: "Hello \(event.name)!")
}

// After
let runtime = LambdaManagedRuntime {
    (event: HelloRequest, context: LambdaContext) in
    HelloResponse(greetings: "Hello \(event.name)!")
}

try await runtime.run()

2. Ensure handlers conform to Sendable:

Since Lambda Managed Instances support concurrent invocations, handlers must be thread-safe:

struct MyHandler: LambdaWithBackgroundProcessingHandler, Sendable {
    typealias Event = MyRequest
    typealias Output = MyResponse
    
    func handle(
        _ event: Event,
        outputWriter: some LambdaResponseWriter<Output>,
        context: LambdaContext
    ) async throws {
        try await outputWriter.write(MyResponse(message: "Processed"))
    }
}

let adapter = LambdaCodableAdapter(handler: MyHandler())
let runtime = LambdaManagedRuntime(handler: adapter)
try await runtime.run()

For simple structs, Swift automatically infers Sendable conformance.

Implementation Highlights

The runtime automatically detects the configured concurrency level (AWS_LAMBDA_MAX_CONCURRENCY) and launches the appropriate number of Runtime Interface Clients to handle concurrent requests. When concurrency is 1 or unset, it maintains single-threaded behavior for optimal performance on traditional Lambda deployments.

This is a purely additive feature with no breaking changes—existing Lambda functions continue to work without modification. The managed instances support is implemented behind a Swift package trait (ManagedRuntimeSupport) that's enabled by default. If you're concerned about binary size and don't need managed instances support, you can disable this specific trait in your Package.swift:

dependencies: [
    .package(
        url: "https://github.com/awslabs/swift-aws-lambda-runtime.git",
        from: "2.0.0",
        traits: [
            // Keep other default traits but exclude ManagedRuntimeSupport
            "FoundationJSONSupport",
            "ServiceLifecycleSupport",
            "LocalServerSupport"
        ]
    ),
],
targets: [
    .executableTarget(
        name: "MyLambda",
        dependencies: [
            .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
        ]
    ),
]

Examples

The release includes three examples demonstrating concurrent execution, streaming responses, and background processing patterns. Check out Examples/ManagedInstances/ in the repository.

Getting Started

You'll need to create a Lambda Managed Instances capacity provider before deploying. See the example README for complete deployment instructions using AWS SAM.

Repository: GitHub - awslabs/swift-aws-lambda-runtime: Swift implementation of AWS Lambda Runtime
Documentation: https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/~/documentation/awslambdaruntime/

We'd love to hear your feedback and use cases for Lambda Managed Instances with Swift!

3 Likes