Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
# These must run on Ubuntu and not in a container, because the plugin uses docker
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
persist-credentials: false

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
timeout-minutes: 1
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Check for Semantic Version label
Expand Down
72 changes: 36 additions & 36 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ This package allows you to develop and deploy AWS Lambda Functions written in Sw
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fawslabs%2Fswift-aws-lambda-runtime%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime)
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fawslabs%2Fswift-aws-lambda-runtime%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime)

You can read [the Swift AWS Lambda Runtime documentation](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/2.3.0/documentation/awslambdaruntime) on the Swift Package Index.
You can read [the Swift AWS Lambda Runtime documentation](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/documentation/awslambdaruntime) on the Swift Package Index.

This guide contains the following sections:

- [The Swift AWS Lambda Runtime](#the-swift-aws-lambda-runtime)
- [Prerequisites](#prerequisites)
- [Getting started](#getting-started)
- [Developing your Swift Lambda functions](#developing-your-swift-lambda-functions)
- [Testing Locally](#testing-locally)
- [Testing locally](#testing-locally)
- [Deploying your Swift Lambda functions](#deploying-your-swift-lambda-functions)
- [Swift AWS Lambda Runtime - Design Principles](#swift-aws-lambda-runtime---design-principles)
- [Swift AWS Lambda Runtime - design principles](#swift-aws-lambda-runtime---design-principles)

The Swift runtime client is [incubating as part of the Swift Server Workgroup incubation process](https://www.swift.org/sswg/incubated-packages.html). It is an experimental package, subject to change, and intended only for evaluation purposes.

Expand All @@ -24,13 +24,13 @@ Open [issues on GitHub for support requests](https://github.com/awslabs/swift-aw

Many modern systems have client components like iOS, macOS or watchOS applications as well as server components that those clients interact with. Serverless functions are often the easiest and most efficient way for client application developers to extend their applications into the cloud.

Serverless functions are increasingly becoming a popular choice for running event-driven or otherwise ad-hoc compute tasks in the cloud. They power mission critical microservices and data intensive workloads. In many cases, serverless functions allow developers to more easily scale and control compute costs given their on-demand nature.
Serverless functions are a popular choice for event-driven or ad-hoc compute tasks in the cloud. They power mission-critical microservices and data-intensive workloads. They also allow developers to scale easily and control compute costs, given their on-demand nature.

When using serverless functions, attention must be given to resource utilization as it directly impacts the costs of the system. This is where Swift shines! With its low memory footprint, deterministic performance, and quick start time, Swift is a fantastic match for the serverless functions architecture.
When using serverless functions, attention must be given to resource utilization as it directly impacts the costs of the system. Swift is well-suited for this. With its low memory footprint, deterministic performance, and quick start time, Swift is a strong match for the serverless functions architecture.

Combine this with Swift's developer friendliness, expressiveness, and emphasis on safety, and we have a solution that is great for developers at all skill levels, scalable, and cost effective.
Combine this with Swift's developer friendliness, expressiveness, and emphasis on safety, and the result is a solution accessible to developers at all skill levels, scalable, and cost-effective.

Swift AWS Lambda Runtime was designed to make building Lambda functions in Swift simple and safe. The library is an implementation of the [AWS Lambda Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html) and uses an embedded asynchronous HTTP Client based on [SwiftNIO](http://github.com/apple/swift-nio) that is fine-tuned for performance in the AWS Runtime context. The library provides a multi-tier API that allows building a range of Lambda functions: From quick and simple closures to complex, performance-sensitive event handlers.
Swift AWS Lambda Runtime was designed to make building Lambda functions in Swift simple and safe. The library is an implementation of the [AWS Lambda Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html) and uses an embedded asynchronous HTTP Client based on [SwiftNIO](http://github.com/apple/swift-nio) that is optimized for performance in the AWS Runtime context. The library provides a layered API that allows building a range of Lambda functions: from simple closures to complex, performance-sensitive event handlers.

## Prerequisites

Expand All @@ -50,11 +50,11 @@ To get started, read [the Swift AWS Lambda runtime tutorial](https://swiftpackag

We also wrote a comprehensive [deployment guide](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/2.3.0/documentation/awslambdaruntime/deployment).

Or, if you're impatient to start with runtime v2, try these six steps:
Or, to get started quickly with runtime v2, try these six steps:

The `Examples/_MyFirstFunction` contains a script that goes through the steps described in this section.

If you are really impatient, just type:
For the fastest path, just type:

```bash
cd Examples/_MyFirstFunction
Expand Down Expand Up @@ -85,7 +85,7 @@ swift package init --type executable --name MyLambda
platforms: [.macOS(.v15)],
```

2.3 Your `Package.swift` file must look like this
2.3 Your `Package.swift` file should look like this

```swift
// swift-tools-version: 6.3
Expand Down Expand Up @@ -117,7 +117,7 @@ The runtime comes with a plugin to generate the code of a simple AWS Lambda func
swift package lambda-init --allow-writing-to-package-directory
```

Your `Sources/main.swift` file must look like this.
Your `Sources/main.swift` file should look like this.

```swift
import AWSLambdaRuntime
Expand Down Expand Up @@ -158,8 +158,8 @@ swift package --disable-sandbox \
If there is no error, the ZIP archive is ready to deploy.
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip`

>[!NOTE]
> If you encounter Docker credential store errors during the build, remove the `credsStore` entry from your `~/.docker/config.json` file or disable the plugin sandbox with `--disable-sandbox`. See [issue #609](https://github.com/awslabs/swift-aws-lambda-runtime/issues/609) for details.
> [!NOTE]
> If you encounter Docker credential store errors during the build, remove the `credsStore` entry from your `~/.docker/config.json` file or disable the plugin sandbox with `--disable-sandbox`. See [issue #609](https://github.com/awslabs/swift-aws-lambda-runtime/issues/609) for details.

> [!NOTE]
> The archive plugin currently defaults to Amazon Linux 2 as the build environment. After June 30, 2026, the default will change to Amazon Linux 2023. To migrate early, add the `--base-docker-image swift:amazonlinux2023` flag to the archive command:
Expand Down Expand Up @@ -188,7 +188,7 @@ aws lambda create-function \

The `--architectures` flag is only required when you build the binary on an Apple Silicon machine (Apple M1 or more recent). It defaults to `x64`.

Be sure to replace <YOUR_ACCOUNT_ID> with your actual AWS account ID (for example: 012345678901).
Replace `<YOUR_ACCOUNT_ID>` with your actual AWS account ID (for example: 012345678901).

> [!IMPORTANT]
> Before creating a function, you need to have a `lambda_basic_execution` IAM role in your AWS account.
Expand Down Expand Up @@ -220,7 +220,7 @@ This should print

### Receive and respond with JSON objects

Typically, your Lambda functions will receive an input parameter expressed as JSON and will respond with some other JSON. The Swift AWS Lambda runtime automatically takes care of encoding and decoding JSON objects when your Lambda function handler accepts `Decodable` and returns `Encodable` conforming types.
Typically, your Lambda functions receive an input parameter expressed as JSON and respond with JSON. The Swift AWS Lambda Runtime automatically encodes and decodes JSON objects when your Lambda function handler accepts `Decodable` and returns `Encodable` conforming types.

Here is an example of a minimal function that accepts a JSON object as input and responds with another JSON object.

Expand Down Expand Up @@ -253,15 +253,15 @@ try await runtime.run()

You can learn how to deploy and invoke this function in [the Hello JSON example README file](Examples/HelloJSON/README.md).

### Lambda Streaming Response
### Lambda streaming response

You can configure your Lambda function to stream response payloads back to clients. Response streaming can benefit latency sensitive applications by improving time to first byte (TTFB) performance. This is because you can send partial responses back to the client as they become available. Additionally, you can use response streaming to build functions that return larger payloads. Response stream payloads have a soft limit of 200 MB as compared to the 6 MB limit for buffered responses. Streaming a response also means that your function doesn’t need to fit the entire response in memory. For very large responses, this can reduce the amount of memory you need to configure for your function.
You can configure your Lambda function to stream response payloads back to clients. Response streaming can benefit latency-sensitive applications by improving time to first byte (TTFB) performance. You can send partial responses back to the client as they become available. Additionally, you can use response streaming to build functions that return larger payloads. Response stream payloads have a soft limit of 200 MB as compared to the 6 MB limit for buffered responses. Streaming a response also means that your function does not need to fit the entire response in memory. For very large responses, this can reduce the amount of memory you need to configure for your function.

Streaming responses incurs a cost. For more information, see [AWS Lambda Pricing](https://aws.amazon.com/lambda/pricing/).
Streaming responses incur a cost. For more information, see [AWS Lambda Pricing](https://aws.amazon.com/lambda/pricing/).

You can stream responses through [Lambda function URLs](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html), the AWS SDK, or using the Lambda [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/dg/API_InvokeWithResponseStream.html) API. In this example, we create an authenticated Lambda function URL.

#### Simple Streaming Example
#### Simple streaming example

Here is an example of a minimal function that streams 10 numbers with an interval of one second for each number.

Expand All @@ -286,11 +286,11 @@ struct SendNumbersWithPause: StreamingLambdaHandler {
}
}

let runtime = LambdaRuntime.init(handler: SendNumbersWithPause())
let runtime = LambdaRuntime(handler: SendNumbersWithPause())
try await runtime.run()
```

#### Streaming with HTTP Headers and Status Code
#### Streaming with HTTP headers and status code

When streaming responses, you can also set HTTP status codes and headers before sending the response body. This is particularly useful when your Lambda function is invoked through API Gateway or Lambda function URLs, allowing you to control the HTTP response metadata.

Expand Down Expand Up @@ -324,7 +324,7 @@ struct StreamingWithHeaders: StreamingLambdaHandler {
}
}

let runtime = LambdaRuntime.init(handler: StreamingWithHeaders())
let runtime = LambdaRuntime(handler: StreamingWithHeaders())
try await runtime.run()
```

Expand All @@ -336,7 +336,7 @@ The `writeStatusAndHeaders` method allows you to:

You can learn how to deploy and invoke this function in [the streaming example README file](Examples/Streaming/README.md).

### Lambda Streaming Response with JSON Input
### Lambda streaming response with JSON input

The Swift AWS Lambda Runtime also provides a convenient interface that combines the benefits of JSON input decoding with response streaming capabilities. This is ideal when you want to receive strongly-typed JSON events while maintaining the ability to stream responses and execute background work.

Expand Down Expand Up @@ -386,7 +386,7 @@ This interface provides:

You can learn how to deploy and invoke this function in [the streaming codable example README file](Examples/StreamingFromEvent/README.md).

### Integration with AWS Services
### Integration with AWS services

Most Lambda functions are triggered by events originating in other AWS services such as `Amazon SNS`, `Amazon SQS` or `AWS APIGateway`.

Expand Down Expand Up @@ -416,7 +416,7 @@ try await runtime.run()

The Swift AWS Lambda Runtime provides built-in support for [Swift Service Lifecycle](https://github.com/swift-server/swift-service-lifecycle), allowing you to manage the lifecycle of your Lambda runtime alongside other services like database clients, HTTP clients, or any other resources that need proper initialization and cleanup.

Here's how to integrate your Lambda function with ServiceLifecycle to manage multiple services:
Here is how to integrate your Lambda function with ServiceLifecycle to manage multiple services:

```swift
import AWSLambdaRuntime
Expand Down Expand Up @@ -483,7 +483,7 @@ let runtime = LambdaManagedRuntime {
try await runtime.run()
```

#### 2. Ensure Handler Functions and Structs are `Sendable`
#### 2. Ensure handler functions and structs are `Sendable`

Because Lambda Managed Instances can run functions concurrently on the same EC2 host, your handler functions or the structs containing them must conform to the `Sendable` protocol:

Expand All @@ -505,15 +505,15 @@ struct MyHandler: LambdaWithBackgroundProcessingHandler, Sendable {
}
}

// Just like with LambdaRuntime, use LambdaCodableAdapter to pass it to LambdaManagedruntime
// Just like with LambdaRuntime, use LambdaCodableAdapter to pass it to LambdaManagedRuntime
let adapter = LambdaCodableAdapter(handler: MyHandler())
let runtime = LambdaManagedRuntime(handler: adapter)
try await runtime.run()
```

For simple data structures, the Swift compiler automatically infers `Sendable` conformance, but we recommand declaring it explicitly for clarity and safety.
For simple data structures, the Swift compiler automatically infers `Sendable` conformance, but we recommend declaring it explicitly for clarity and safety.

#### Key Benefits
#### Key benefits

- **EC2 Flexibility**: Run on specialized EC2 instance types including Graviton4 and network-optimized instances
- **Cost Optimization**: Better cost efficiency for sustained workloads
Expand All @@ -531,7 +531,7 @@ You can see complete working examples in the [ManagedInstances example directory

For more information, see the [AWS Lambda Managed Instances documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances.html) and the [execution environment guide](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances-execution-environment.html).

### Use Lambda Background Tasks
### Use Lambda background tasks

Background tasks allow code to execute asynchronously after the main response has been returned, enabling additional processing without affecting response latency. This approach is ideal for scenarios like logging, data updates, or notifications that can be deferred. The code leverages Lambda's "Response Streaming" feature, which is effective for balancing real-time user responsiveness with the ability to perform extended tasks post-response. For more information about Lambda background tasks, see [this AWS blog post](https://aws.amazon.com/blogs/compute/running-code-after-returning-a-response-from-an-aws-lambda-function/).

Expand Down Expand Up @@ -578,13 +578,13 @@ struct BackgroundProcessingHandler: LambdaWithBackgroundProcessingHandler {
}

let adapter = LambdaCodableAdapter(handler: BackgroundProcessingHandler())
let runtime = LambdaRuntime.init(handler: adapter)
let runtime = LambdaRuntime(handler: adapter)
try await runtime.run()
```

You can learn how to deploy and invoke this function in [the background tasks example README file](Examples/BackgroundTasks/README.md).

## Testing Locally
## Testing locally

Before deploying your code to AWS Lambda, you can test it locally by running the executable target on your local machine. It will look like this on CLI:

Expand Down Expand Up @@ -637,7 +637,7 @@ LOCAL_LAMBDA_PORT=8080 LOCAL_LAMBDA_INVOCATION_ENDPOINT=/2015-03-31/functions/fu

There is a full deployment guide available in [the documentation](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/2.3.0/documentation/awslambdaruntime/deployment).

There are multiple ways to deploy your Swift code to AWS Lambda. The very first time, you'll probably use the AWS Console to create a new Lambda function and upload your code as a zip file. However, as you iterate on your code, you'll want to automate the deployment process.
There are multiple ways to deploy your Swift code to AWS Lambda. The first time, you will likely use the AWS Console to create a new Lambda function and upload your code as a zip file. However, as you iterate on your code, you will want to automate the deployment process.

To take full advantage of the cloud, we recommend using Infrastructure as Code (IaC) tools like the [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/) or [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/). These tools allow you to define your infrastructure and deployment process as code, which can be version-controlled and automated.

Expand Down Expand Up @@ -675,13 +675,13 @@ Value https://a5q74es3k2.execute-api.us-east-1.amazonaws.com

Please refer to [the full deployment guide available in the documentation](https://swiftpackageindex.com/awslabs/swift-aws-lambda-runtime/2.3.0/documentation/awslambdaruntime/deployment) for more details.

## Swift AWS Lambda Runtime - Design Principles
## Swift AWS Lambda Runtime - design principles

The [design document](Sources/AWSLambdaRuntime/Docs.docc/Proposals/0001-v2-api.md) details the v2 API proposal for the swift-aws-lambda-runtime library, which aims to enhance the developer experience for building serverless functions in Swift.

The proposal has been reviewed and [incorporated feedback from the community](https://forums.swift.org/t/aws-lambda-v2-api-proposal/73819). The full v2 API design document is available [in this repository](Sources/AWSLambdaRuntime/Docs.docc/Proposals/0001-v2-api.md).

### Key Design Principles
### Key design principles

The v2 API prioritizes the following principles:

Expand All @@ -691,7 +691,7 @@ The v2 API prioritizes the following principles:

- Simplified Codable Support: The `LambdaCodableAdapter` struct eliminates the need for verbose boilerplate code when encoding and decoding events and responses.

### New Capabilities
### New capabilities

The v2 API introduces two new features:

Expand Down
Loading