Skip to content
Open
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
52a8088
chore: point lambda_http at SnapStart-enabled runtime branch
bnusunny Jun 22, 2026
4fe79f4
feat: add SnapStart hook-path environment variables
bnusunny Jun 22, 2026
d273379
test: merge SnapStart env-var tests to avoid parallel race
bnusunny Jun 22, 2026
4b24649
refactor: extract build_client() and drop SnapStart pool special-case
bnusunny Jun 22, 2026
907ca76
feat: add swappable restored_client with write-once OnceLock
bnusunny Jun 22, 2026
20e316d
refactor: return BoxBody<Bytes, Error> from fetch_response
bnusunny Jun 22, 2026
5d2792d
feat: reject external requests to SnapStart hook paths with 403
bnusunny Jun 22, 2026
e600092
feat: add SnapStartHooks bridging restore lifecycle to inner app
bnusunny Jun 22, 2026
c7eddf4
feat: register SnapStart resource in adapter run loop
bnusunny Jun 22, 2026
637e744
docs: document SnapStart hook environment variables
bnusunny Jun 22, 2026
acea58f
docs(guide): add SnapStart feature page and env vars
bnusunny Jun 22, 2026
2883c29
docs: add fastapi-snapstart-zip example
bnusunny Jun 22, 2026
f8efd16
docs: link fastapi-snapstart example from README
bnusunny Jun 22, 2026
e65b8ea
docs: drop /lwa prefix from SnapStart example hook paths
bnusunny Jun 22, 2026
8255b57
refactor: extract register_and_run helper to dedup run() arms
bnusunny Jun 22, 2026
1d6b488
feat: add 60s timeout to SnapStart inner-app hooks
bnusunny Jun 23, 2026
464390a
feat: re-run readiness check after SnapStart restore
bnusunny Jun 29, 2026
07fabdd
docs: add fastapi-snapstart (OCI) example
bnusunny Jun 29, 2026
a1b49c5
refactor: move SnapStart hook env vars to SAM template in OCI example
bnusunny Jun 29, 2026
bcfba60
chore: point OCI example at 1.1.0 SnapStart-enabled adapter image
bnusunny Jun 29, 2026
1aa3939
chore: use public ECR adapter image in OCI SnapStart example
bnusunny Jun 29, 2026
c27e419
docs: correct after-restore step ordering in OCI example README
bnusunny Jun 29, 2026
59ca48b
docs: correct after-restore step ordering in zip example README
bnusunny Jun 29, 2026
5968828
docs: fix incorrect AWS_LAMBDA_INITIALIZATION_TYPE claim in snapstart…
bnusunny Jun 29, 2026
ddda3be
chore: use released lambda_http 1.3.0 with SnapStart support
bnusunny Jul 9, 2026
534824f
docs: add SnapStart to README features list
bnusunny Jul 9, 2026
592bb5a
fix: reseed RNG in after-restore hook so restored envs get unique ids
bnusunny Jul 9, 2026
2135560
Merge branch 'main' into snapstart-support
bnusunny Sep 1, 2026
5ecfb7b
fix(snapstart): strict fail-closed hook-path guard + segment-aware ba…
bnusunny Sep 2, 2026
4ce84bb
fix(snapstart): address bot review on hook guard + base-path strip
bnusunny Sep 2, 2026
a0900d3
fix(snapstart): address bot round-2 on hook guard edge cases
bnusunny Sep 2, 2026
5ee28f2
docs(snapstart): re-export Bytes/BoxBody and note the Service::Respon…
bnusunny Sep 2, 2026
3623ee1
fix(snapstart): decode hook path a single pass to match the app router
bnusunny Sep 2, 2026
e42f98b
fix(snapstart): guard the outbound app_url path, not the raw event path
bnusunny Sep 2, 2026
cb9001c
docs(changelog): note the base-path strip behavior change
bnusunny Sep 2, 2026
0c790e4
fix(snapstart): treat an undecidable request path as not-the-hook
bnusunny Sep 2, 2026
c39bd8c
docs: remove launched SnapStart-OCI availability note; bump zip examp…
bnusunny Sep 2, 2026
aeec08d
feat: make inner-app connection pool idle timeout configurable via AW…
bnusunny Sep 2, 2026
2504a11
refactor: move pool_idle_timeout into AdapterOptions and thread it th…
bnusunny Sep 2, 2026
6368cc5
feat: add configurable readiness-check timeout (AWS_LWA_READINESS_CHE…
bnusunny Sep 2, 2026
310e1bf
feat: accept fractional seconds for AWS_LWA_READINESS_CHECK_TIMEOUT_S…
bnusunny Sep 2, 2026
caf54a9
docs: correct stale 10s readiness bound to configurable/unbounded-by-…
bnusunny Sep 2, 2026
76f17ba
docs: correct remaining stale 10s readiness bounds in README and exam…
bnusunny Sep 2, 2026
cfcc875
feat: fail initialization when a configured sync-init readiness timeo…
bnusunny Sep 2, 2026
32a02b9
fix: normalize configured hook path via set_path so guard protects th…
bnusunny Sep 2, 2026
6378296
fix: treat a hook path that canonicalizes to root as no-hook; documen…
bnusunny Sep 2, 2026
9218bf3
fix: strip matrix/path parameters in hook-path canonicalization
bnusunny Sep 2, 2026
dd40ad7
fix: restore TracingLayer on concurrent runtime path; warn on rejecte…
bnusunny Sep 3, 2026
726d37d
feat: mark AdapterOptions #[non_exhaustive]; warn on <=0 readiness ti…
bnusunny Sep 3, 2026
30006a1
fix: restore pool_max_idle_per_host(0) on base client under snap-start
bnusunny Sep 3, 2026
0a3a232
chore: mark crate publish = false (binary-only; no published library …
bnusunny Sep 3, 2026
b2fb939
docs: correct Adapter::new rustdoc for configurable idle timeout and …
bnusunny Sep 3, 2026
8004456
chore: frame publish=false as a deliberate stop-publishing policy; dr…
bnusunny Sep 3, 2026
1c181e0
docs: scope hook-path 403 protection to the Lambda invocation path; d…
bnusunny Sep 3, 2026
7e30ce2
docs: correct 'fail closed' guard comments to match pass-through beha…
bnusunny Sep 3, 2026
2098a21
fix: block hook paths with encoded control bytes (e.g. /snapstart/aft…
bnusunny Sep 3, 2026
9434eaa
docs: trim CHANGELOG to net release-visible changes
bnusunny Sep 3, 2026
ca56fd9
fix(snapstart): reject unguardable hook paths instead of degrading th…
bnusunny Sep 3, 2026
d6f802c
fix(snapstart): reject a hook path that collapses to the app root
bnusunny Sep 3, 2026
be50614
fix(snapstart): make AWS_LWA_POOL_IDLE_TIMEOUT_SECONDS effective unde…
bnusunny Sep 3, 2026
02ddf85
fix(snapstart): close the empty-hook-path divergence; drop dead readi…
bnusunny Sep 3, 2026
81fadbd
fix(snapstart): disable the pre-snapshot pool instead of zero-expirin…
bnusunny Sep 3, 2026
de0ea31
fix(snapstart): reject hook paths colliding with the pass-through pat…
bnusunny Sep 3, 2026
f6679db
fix(snapstart): don't fail init on an unguardable pass-through path
bnusunny Sep 3, 2026
928bc8c
fix(snapstart): adopt the published client when after_restore runs twice
bnusunny Sep 3, 2026
db37e17
fix(snapstart): disable idle pooling on the Lambda Runtime API client
bnusunny Sep 3, 2026
02acbd5
docs(snapstart): record why the two pooling sites deliberately disagree
bnusunny Sep 3, 2026
37e5f2f
docs: add the non-Lambda hook-exposure caveat to the README
bnusunny Sep 3, 2026
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
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
## Unreleased

### Features

- Add SnapStart support. The adapter notifies your web application at the SnapStart
boundary via two opt-in HTTP hooks — `AWS_LWA_SNAPSTART_BEFORE_CHECKPOINT_PATH`
(before checkpoint) and `AWS_LWA_SNAPSTART_AFTER_RESTORE_PATH` (after restore) —
so it can drain and re-establish connections. Each hook call is bounded by a
60-second timeout. After restore the adapter refreshes its own HTTP client and
re-runs the readiness check before admitting traffic, and it rejects external
traffic to the hook paths with 403.
- The crate now stops publishing to crates.io (`publish = false`): Lambda Web
Adapter ships as the `lambda-adapter` binary (a Lambda layer / copied
extension), not as a library, so the `lib` target has no external
API-stability contract. The internal changes SnapStart required — the
`tower::Service` impl's `Response` is now `Response<BoxBody<Bytes, Error>>`
(was `Response<Incoming>`) and `check_init_health` now returns `Result` —
therefore do not affect any published API. `Bytes` and `BoxBody` are
re-exported for convenience of in-repo `Service` users. Existing crates.io
consumers keep the last published release (`1.0.0-rc1`) unchanged.
- Add `AWS_LWA_POOL_IDLE_TIMEOUT_SECONDS` to configure the idle keep-alive (in
whole seconds) of the adapter's HTTP connection to your app. Default: 4 seconds.
- Add `AWS_LWA_READINESS_CHECK_TIMEOUT_SECONDS` to bound the readiness check
(fractional seconds allowed, e.g. `0.5`), applied to both the initial cold-start
readiness wait and the
post-SnapStart-restore readiness check. When set and the app does not become
ready within it, the adapter **refuses to serve**: cold-start init fails (the
runtime never starts) and a restore fails, rather than admitting traffic to an
app that never reported ready. When unset (the default) the wait is
**unbounded**, matching the previous behavior, so existing slow-cold-start apps
are unaffected unless they opt in. The `async_init` initial-readiness path keeps
its own fixed ~9.8s bound (non-fatal) and is not affected by this variable.

### Bug Fixes

- Fix `AWS_LWA_REMOVE_BASE_PATH` stripping to remove exactly one leading occurrence
on a path-segment boundary. Previously it used `trim_start_matches`, which stripped
the prefix repeatedly and byte-wise: with `AWS_LWA_REMOVE_BASE_PATH=/api`,
`/api/api/order` became `/order` (both copies removed) and `/apiorder` became
`/order` (a partial segment stripped). Now `/api/api/order` → `/api/order` and
`/apiorder` is passed through unchanged, and a configured trailing slash (`/api/`)
is normalized so it behaves like `/api`. **Upgrade note:** this changes the path
forwarded to your app for those inputs — deployments that relied on the old
repeated/partial stripping should verify their routes.

---

## v1.0.1 - 2026-05-28

### Bug Fixes
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ keywords = ["AWS", "Lambda", "APIGateway", "ALB", "API"]
license = "Apache-2.0"
homepage = "https://github.com/aws/aws-lambda-web-adapter"
repository = "https://github.com/aws/aws-lambda-web-adapter"
documentation = "https://docs.rs/lambda_web_adapter"
categories = ["web-programming::http-server"]
readme = "README.md"
exclude = ["examples"]
# Lambda Web Adapter ships as the `lambda-adapter` binary (packaged as a Lambda
# layer / container-copied extension), not as a library. This stops publishing the
# crate to crates.io: the `lib` target is an internal implementation detail of the
# binary and tests, with no external API-stability contract.
#
# Note for crates.io consumers: earlier `0.x` / `1.0.0-rc1` releases remain
# available and unchanged; they are simply the last published versions. New
# development ships only as the binary/layer.
publish = false
Comment thread
bnusunny marked this conversation as resolved.

[dependencies]
bytes = "1.9.0"
Expand All @@ -23,7 +31,7 @@ http-body = "1.0.1"
http-body-util = "0.1.0"
hyper = { version = "1.5.2", features = ["client"] }
hyper-util = "0.1.10"
lambda_http = { version = "1.1.1", default-features = false, features = [
lambda_http = { version = "1.3.0", default-features = false, features = [
"apigw_http",
"apigw_rest",
"alb",
Expand Down
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The same docker image can run on AWS Lambda, Amazon EC2, AWS Fargate, and local
- Supports Amazon API Gateway Rest API and Http API endpoints, Lambda Function URLs, and Application Load Balancer
- Supports Lambda managed runtimes, custom runtimes and docker OCI images
- Supports Lambda Managed Instances for multi-concurrent request handling
- Supports Lambda SnapStart with before-checkpoint and after-restore hooks
- Supports any web frameworks and languages, no new code dependency to include
- Automatic encode binary response
- Enables graceful shutdown
Expand Down Expand Up @@ -59,13 +60,17 @@ The readiness check port/path and traffic port can be configured using environme
| AWS_LWA_READINESS_CHECK_PROTOCOL | readiness check protocol: "http" or "tcp" | "http" |
| AWS_LWA_READINESS_CHECK_HEALTHY_STATUS | HTTP status codes considered healthy (e.g., "200-399") | "100-499" |
| AWS_LWA_ASYNC_INIT | enable asynchronous initialization for long initialization functions | "false" |
| AWS_LWA_REMOVE_BASE_PATH | the base path to be removed from request path | None |
| AWS_LWA_REMOVE_BASE_PATH | base path to remove from the request path; strips exactly one leading occurrence on a segment boundary (with `/api`: `/api/api/order`->`/api/order`, `/apiorder` unchanged; trailing slash normalized) | None |
| AWS_LWA_ENABLE_COMPRESSION | enable gzip/br compression for response body (buffered mode only) | "false" |
| AWS_LWA_INVOKE_MODE | Lambda function invoke mode: "buffered" or "response_stream" | "buffered" |
| AWS_LWA_PASS_THROUGH_PATH | the path for receiving event payloads from non-http triggers | "/events" |
| AWS_LWA_AUTHORIZATION_SOURCE | a header name to be replaced to `Authorization` | None |
| AWS_LWA_ERROR_STATUS_CODES | HTTP status codes that will cause Lambda invocations to fail (e.g. "500,502-504") | None |
| AWS_LWA_LAMBDA_RUNTIME_API_PROXY | overwrites `AWS_LAMBDA_RUNTIME_API` to allow proxying request | None |
| AWS_LWA_SNAPSTART_BEFORE_CHECKPOINT_PATH | inner-app path the adapter POSTs to before a SnapStart snapshot (drain resources) | None |
| AWS_LWA_SNAPSTART_AFTER_RESTORE_PATH | inner-app path the adapter POSTs to after a SnapStart restore (reconnect/reseed) | None |
| AWS_LWA_POOL_IDLE_TIMEOUT_SECONDS | idle keep-alive (seconds) for the adapter's connection to your app | "4" |
| AWS_LWA_READINESS_CHECK_TIMEOUT_SECONDS | seconds (fractional allowed, e.g. 0.5) to wait for the app to report ready (cold-start init and after a SnapStart restore); on expiry the adapter FAILS (init fails and the runtime never starts; a restore fails) rather than serving. Unset, 0, or negative all mean wait indefinitely (a set-but-<=0 or malformed value is ignored with a warning). async_init keeps its own ~9.8s bound | unset / <=0 (unbounded) |

> **Deprecation Notice:** The following non-namespaced environment variables are deprecated and will be removed in version 2.0:
> `HOST`, `READINESS_CHECK_PORT`, `READINESS_CHECK_PATH`, `READINESS_CHECK_PROTOCOL`, `REMOVE_BASE_PATH`, `ASYNC_INIT`.
Expand All @@ -75,6 +80,38 @@ The readiness check port/path and traffic port can be configured using environme

👉 [Detailed configuration docs](https://aws.github.io/aws-lambda-web-adapter/configuration/environment-variables.html)

### SnapStart support

When your function uses [Lambda SnapStart](https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html),
the adapter can notify your web application at the snapshot boundary so it can
drain and re-establish state (database connections, cached DNS, PRNG seeds,
unique identifiers). Both hooks are opt-in and independent.

| Variable | When the adapter calls it | Use it to |
|---|---|---|
| `AWS_LWA_SNAPSTART_BEFORE_CHECKPOINT_PATH` | Before the snapshot is taken | Drain/close resources that won't survive the snapshot |
| `AWS_LWA_SNAPSTART_AFTER_RESTORE_PATH` | After restore, before serving traffic | Reconnect, refresh credentials, reseed randomness, regenerate unique IDs |

Each hook is an empty `POST`; your application must respond with a `2xx` status.
A non-`2xx` response, a connection failure, or taking longer than 60 seconds to
respond fails the SnapStart phase (initialization for the before-checkpoint hook,
restore for the after-restore hook) instead of serving traffic against an
improperly prepared application.

After restore, the adapter also automatically refreshes its own HTTP connection
to your application, so it never reuses a connection captured in the snapshot, and
then re-runs the readiness check before admitting traffic. By default this wait is
unbounded; set `AWS_LWA_READINESS_CHECK_TIMEOUT_SECONDS` (fractional seconds allowed)
to bound it, in which case a restore whose application does not report ready within
that timeout fails.

> These hook paths are control-plane operations. External requests (via API
Comment thread
bnusunny marked this conversation as resolved.
Comment thread
bnusunny marked this conversation as resolved.
> Gateway or ALB) that target a configured hook path receive `403 Forbidden` and
> are never forwarded to your application, so choose paths your normal traffic
> does not use.

See the [FastAPI with SnapStart example](examples/fastapi-snapstart-zip) for a complete, deployable application.

## Examples

- [FastAPI](examples/fastapi)
Expand All @@ -84,6 +121,8 @@ The readiness check port/path and traffic port can be configured using environme
- [FastAPI with Response Streaming in Zip](examples/fastapi-response-streaming-zip)
- [FastAPI with Response Streaming on Lambda Managed Instances](examples/fastapi-response-streaming-lmi)
- [FastAPI Response Streaming Backend with IAM Auth](examples/fastapi-backend-only-response-streaming/)
- [FastAPI with SnapStart](examples/fastapi-snapstart)
- [FastAPI with SnapStart in Zip](examples/fastapi-snapstart-zip)
- [Flask](examples/flask)
- [Flask in Zip](examples/flask-zip)
- [Serverless Django](https://github.com/aws-hebrew-book/serverless-django) by [@efi-mk](https://github.com/efi-mk)
Expand Down
1 change: 1 addition & 0 deletions docs/guide/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- [Non-HTTP Event Triggers](./features/non-http-events.md)
- [Multi-Tenancy](./features/multi-tenancy.md)
- [Lambda Managed Instances](./features/managed-instances.md)
- [SnapStart](./features/snapstart.md)
- [Graceful Shutdown](./features/graceful-shutdown.md)
- [Base Path Removal](./features/base-path-removal.md)
- [Authorization Header](./features/authorization-header.md)
Expand Down
6 changes: 5 additions & 1 deletion docs/guide/src/configuration/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ All configuration is done through environment variables, set either in your Dock
| `AWS_LWA_READINESS_CHECK_PROTOCOL` | Readiness check protocol: `http` or `tcp` | `http` |
| `AWS_LWA_READINESS_CHECK_HEALTHY_STATUS` | HTTP status codes considered healthy (e.g. `200-399` or `200,201,204,301-399`) | `100-499` |
| `AWS_LWA_ASYNC_INIT` | Enable asynchronous initialization | `false` |
| `AWS_LWA_REMOVE_BASE_PATH` | Base path to remove from request path | None |
| `AWS_LWA_REMOVE_BASE_PATH` | Base path to remove from the request path. Strips **exactly one** leading occurrence and only on a path-segment boundary: with `/api`, `/api/api/order` → `/api/order` and `/apiorder` is passed through unchanged; a configured trailing slash (`/api/`) is normalized. | None |
| `AWS_LWA_ENABLE_COMPRESSION` | Enable gzip/br compression (buffered mode only) | `false` |
| `AWS_LWA_INVOKE_MODE` | Invoke mode: `buffered` or `response_stream` | `buffered` |
| `AWS_LWA_PASS_THROUGH_PATH` | Path for non-HTTP event payloads | `/events` |
| `AWS_LWA_AUTHORIZATION_SOURCE` | Header name to replace with `Authorization` | None |
| `AWS_LWA_ERROR_STATUS_CODES` | HTTP status codes that cause Lambda invocation failure (e.g. `500,502-504`) | None |
| `AWS_LWA_LAMBDA_RUNTIME_API_PROXY` | Proxy URL for Lambda Runtime API requests | None |
| `AWS_LWA_SNAPSTART_BEFORE_CHECKPOINT_PATH` | Inner-app path the adapter POSTs to before a SnapStart snapshot | None |
| `AWS_LWA_SNAPSTART_AFTER_RESTORE_PATH` | Inner-app path the adapter POSTs to after a SnapStart restore | None |
| `AWS_LWA_POOL_IDLE_TIMEOUT_SECONDS` | Idle keep-alive (seconds) for the adapter's connection to your app | `4` |
Comment thread
bnusunny marked this conversation as resolved.
| `AWS_LWA_READINESS_CHECK_TIMEOUT_SECONDS` | Seconds (fractional allowed, e.g. `0.5`) the adapter waits for the app to report ready (cold-start init **and** after a SnapStart restore). On expiry the adapter **fails** rather than serving: cold-start init fails (the runtime never starts) and a restore fails. Unset, `0`, or a negative value all mean **wait indefinitely** (no bound); a set-but-`<= 0` or malformed value is ignored with a `warn!`. The `async_init` path keeps its own ~9.8s bound (non-fatal) and is unaffected. | unset / `<= 0` (unbounded) |

## Deprecated Variables

Expand Down
2 changes: 2 additions & 0 deletions docs/guide/src/examples/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The repository includes working examples for many popular web frameworks, packag
|---------|-----------|-----------|
| [FastAPI](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi) | Docker | No |
| [FastAPI in Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-zip) | Zip | No |
| [FastAPI SnapStart](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-snapstart) | Docker | No |
| [FastAPI SnapStart Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-snapstart-zip) | Zip | No |
| [FastAPI Background Tasks](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-background-tasks) | Docker | No |
| [FastAPI Response Streaming](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming) | Docker | Yes |
| [FastAPI Response Streaming Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming-zip) | Zip | Yes |
Expand Down
Loading
Loading