Serve — Lambda Web Adapter
Deploy a Rank HTTP app to AWS Lambda using the Lambda Web Adapter and a provided.al2023 custom runtime — no container image required.
The adapter is attached as a Lambda Layer. It translates Lambda invocations into HTTP requests forwarded to rank serve, so the Rank app needs no Lambda-specific handler code.
Source
use std::HTTP
use std::Runtime
HealthRoute = HTTP::Route {
method: `GET`,
path: `/health`
}
Routes = HealthRoute
pub config = {
defaultResponseFormat: `json`
}
pub main = |req: Runtime::ExecutionContext<Routes>| -> HTTP::Response {
return {
status: 200,
body: {
ok: true,
service: `serve-lambda-web-adapter-example`
}
}
}
#!/bin/sh
export PATH="$LAMBDA_TASK_ROOT/bin:$LAMBDA_TASK_ROOT/node_modules/.bin:$PATH"
exec rank serve "$LAMBDA_TASK_ROOT" --host 0.0.0.0 --port "${PORT:-8080}"
.PHONY: build-RankApp
build-RankApp:
dnf install -y nodejs npm 2>/dev/null || true
npm install --prefix "$(ARTIFACTS_DIR)" @rank-lang/cli
"$(ARTIFACTS_DIR)/node_modules/.bin/rank" sync .
cp main.rank rank.toml "$(ARTIFACTS_DIR)/"
cp bootstrap "$(ARTIFACTS_DIR)/"
chmod +x "$(ARTIFACTS_DIR)/bootstrap"
mkdir -p "$(ARTIFACTS_DIR)/bin"
cp "$$(which node)" "$(ARTIFACTS_DIR)/bin/"
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 30
MemorySize: 512
Resources:
RankApp:
Type: AWS::Serverless::Function
Properties:
Runtime: provided.al2023
Architectures:
- x86_64
Handler: bootstrap
CodeUri: ./
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerX86:24
Environment:
Variables:
PORT: '8080'
READINESS_CHECK_PATH: /.well-known/rank/ready
Events:
Api:
Type: HttpApi
Properties:
Path: /{proxy+}
Method: ANY
RootApi:
Type: HttpApi
Properties:
Path: /
Method: ANY
Metadata:
BuildMethod: makefile
Outputs:
ApiUrl:
Description: API Gateway endpoint
Value: !Sub https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com
Build and deploy
Requires the AWS SAM CLI. Docker is used only for the SAM container build step, not the Lambda runtime.
There is no separate Rank compile step for this example. The Lambda source bundle is the example directory itself:
main.rankis the Rank app source.rank.tomlmakes the directory runnable asrank serve ..bootstrapis the custom runtime entrypoint Lambda executes.template.yamltells SAM to build the function with the localMakefileviaBuildMethod: makefile.
Run the build from examples/serve-lambda:
cd examples/serve-lambda
# Build inside an Amazon Linux 2023 container so node matches the runtime
sam build --use-container
# First deploy (creates samconfig.toml)
sam deploy --guided
During sam build, SAM invokes the build-RankApp target from Makefile inside the AL2023 build container. The target name is build-<LogicalId>, so it matches the function resource name RankApp in template.yaml. SAM also sets ARTIFACTS_DIR to the staging directory that will become the Lambda bundle.
That target:
- Installs Node.js via
dnf - Installs
@rank-lang/cliinto the artifact directory - Runs
rank sync .to pre-cache registry dependencies - Copies
main.rank,rank.toml, andbootstrapinto the Lambda artifact directory - Copies the node binary so it is available at
$LAMBDA_TASK_ROOT/bin/nodeat runtime
After the build, the staged Lambda bundle is under .aws-sam/build/RankApp/. That directory is what SAM deploys to Lambda.
Test it
curl https://<api-id>.execute-api.<region>.amazonaws.com/health
{
"ok": true,
"service": "serve-lambda-web-adapter-example"
}
Local testing without Lambda:
rank serve . --host 127.0.0.1 --port 8080
Or with the SAM local emulator:
sam local start-api --port 8080
Key concepts
Runtime: provided.al2023— Lambda calls thebootstrapexecutable directly. No managed runtime is involved; rank serve is the only process.- Lambda Web Adapter layer — the
LambdaAdapterLayerX86layer adds an extension that translates Lambda invocations into HTTP requests and forwards them to the server onPORT. PORT=8080— the adapter forwards traffic to rank serve on this port.READINESS_CHECK_PATH=/.well-known/rank/ready— the adapter polls this built-in endpoint on startup and withholds traffic until rank serve is ready to accept connections.rank sync .at build time — caches registry dependencies so cold starts don't need outbound package requests.- No Lambda handler — the Rank app is unaware it runs on Lambda. The same
rank servecommand works locally and behind the adapter.