Skip to content

feat: add Lambda SnapStart support#790

Merged
bnusunny merged 27 commits into
mainfrom
snapstart-support
Jul 9, 2026
Merged

feat: add Lambda SnapStart support#790
bnusunny merged 27 commits into
mainfrom
snapstart-support

Conversation

@bnusunny

@bnusunny bnusunny commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds AWS Lambda SnapStart support to the Lambda Web Adapter. Because the adapter runs the customer's web application as a separate process with no access to the Lambda Runtime API, the application cannot participate in the SnapStart lifecycle on its own. This PR makes the adapter a SnapStart bridge: it registers the runtime's SnapStartResource hooks and relays the before-checkpoint and after-restore lifecycle events to the inner application over HTTP.

What it does

Two opt-in, independent environment variables:

Variable When Purpose
AWS_LWA_SNAPSTART_BEFORE_CHECKPOINT_PATH before the snapshot app drains/closes resources that won't survive the snapshot
AWS_LWA_SNAPSTART_AFTER_RESTORE_PATH after restore app reconnects, reseeds RNG, regenerates per-environment unique IDs

after_restore() performs three ordered steps (before any invocation is served):

  1. Refresh the adapter's own HTTP client (write-once OnceLock) so it never reuses a connection captured in the snapshot — this happens first so the hook call itself uses a fresh connection.
  2. POST the after-restore hook over that fresh client (if configured).
  3. Re-run the readiness check against the app.

Each hook POST is bounded by a 60s timeout; the post-restore readiness check is bounded by a tighter 10s timeout. A non-2xx, connection error, or timeout at any step fails the SnapStart phase (/init/error for before-checkpoint, /restore/error for after-restore) rather than serving traffic against an improperly restored app.

Security: the hook routes live on the app's HTTP surface, so external requests (via API Gateway/ALB) targeting a configured hook path receive 403 Forbidden and are never forwarded to the app.

Behavior is unchanged when SnapStart is not in use — the runtime lifecycle is a no-op, and the hooks are unset by default. The previous pool_max_idle_per_host(0) SnapStart special-case is removed in favor of the at-restore client swap, which restores connection pooling for steady-state throughput.

Notable implementation details

  • Depends on the released lambda_http/lambda_runtime 1.3.0 (adds the SnapStartResource API).
  • fetch_response return type changed to Response<BoxBody<Bytes, Error>> so the synthetic 403 can share the return type with proxied responses.
  • Readiness-check logic extracted into shared free functions in readiness.rs, reused by both the adapter and the after-restore step.

Testing

  • Unit tests for the hooks (before/after, unset/non-2xx/timeout), the client swap, the 403 guard, and env-var parsing.
  • Verified end-to-end on real Lambda SnapStart (container image): the success path fires before → after → readiness and serves with a fresh connection_id; the failure path (unready app) times out the readiness check at ~10s and fails the restore with SnapStartTimeoutException.
  • cargo test, cargo clippy --all-targets -- -Dwarnings, and cargo fmt --check all pass.

Examples

Two deployable examples: examples/fastapi-snapstart (container image / OCI) and examples/fastapi-snapstart-zip (managed runtime layer), each demonstrating connection drain/reconnect across a restore.

@bnusunny
bnusunny requested a review from a team as a code owner July 9, 2026 16:11

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: e4e29e5..b28a336
Files: 26
Comments: 2

Comment thread examples/fastapi-snapstart/app/main.py
Comment thread examples/fastapi-snapstart-zip/app/main.py
@bnusunny
bnusunny force-pushed the snapstart-support branch from b28a336 to 9fa790d Compare July 9, 2026 16:17
bnusunny added 26 commits July 9, 2026 16:19
Switch from the git-branch dependency to the published lambda_http/lambda_runtime
1.3.0 from crates.io, removing the release blocker. Also fix the integration test
body-reader helpers to accept the BoxBody response type, and resolve a clippy
ok().expect() lint.

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Results

Reviewed: e4e29e5..9fa790d
Files: 26
Comments: 2

Comment thread examples/fastapi-snapstart/app/main.py
Comment thread examples/fastapi-snapstart-zip/app/main.py
@bnusunny
bnusunny force-pushed the snapstart-support branch from 9fa790d to ada9aa2 Compare July 9, 2026 16:21
@@ -0,0 +1,65 @@
import os

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:import os is not used

@bnusunny
bnusunny merged commit 48caa3d into main Jul 9, 2026
28 checks passed
@bnusunny
bnusunny deleted the snapstart-support branch July 9, 2026 17:09
bnusunny added a commit that referenced this pull request Jul 10, 2026
* Revert "chore: release v1.1.0 (#792)"

This reverts commit 87f0c87.

* Revert "feat: add Lambda SnapStart support (#790)"

This reverts commit 48caa3d.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants