This guide covers:
libpq
Install these tools:
brew install rustup awscli docker aws-sam-cli
cargo install cargo-watch # for hot reloads
brew install act # optional: test CI locally
git clone https://github.com/apjames93/warp-lambda-starter.git
cd warp-lambda-starter
Youβll get:
.
βββ backend/ # Rust source
βββ aws/ # SAM template, Docker builds
βββ aws/libpq_layer/ # Prebuilt libpq + OpenSSL
βββ docker-compose.yaml # Local Postgres
βββ Makefile # Build/run shortcuts
βββ .github/workflows/ # CI pipeline
Run PostgreSQL (pgvector-enabled) locally:
docker-compose up
Access it via:
postgres://root:password@localhost:5001/test
Inside SAM (Docker network sam-local
):
"DATABASE_URL": "postgres://root:password@test-db:5432/test?sslmode=disable"
Quick start: The
aws/libpq_layer/
directory is pre-committed so you can start building and deploying immediately.Advanced: If you want to regenerate the layer (e.g. for a different PostgreSQL version, security updates, or reduced size), run:
make aws-docker-sh-libpq
This command:
libpq.a
, libssl.a
, and headers using Alpine + muslaws/libpq_layer/{lib, include}
libpq_layer.zip
for AWS Lambda useYouβre free to customize or rebuild the layer anytimeβjust modify aws/docker/build_libpq_layer_docker.sh
.
Rebuild if:
Compile for Lambda using a dedicated Dockerfile:
make aws-build-sam
musl
toolchainlibpq
, libssl
, zlib
bootstrap
binarysam build
to package itSet in Docker:
RUSTFLAGS="-L /aws/libpq_layer/lib \
-C link-arg=-lpq -C link-arg=-lssl -C link-arg=-lcrypto \
-C link-arg=-lz -C link-arg=-static"
Your main.rs
supports both:
#[cfg(feature = "lambda")]
warp_lambda::run(service).await?;
#[cfg(not(feature = "lambda"))]
warp::serve(routes).run(([0, 0, 0, 0], 3000)).await;
In Cargo.toml
:
[features]
default = ["lambda"]
lambda = ["lambda_http", "lambda_runtime"]
So you can:
cargo run
make aws-build-sam
If you want to clean up your stack after testing or deployment:
make aws-delete-sam
This deletes the deployed stack using sam delete βno-prompts
Even with static linking, Lambda may expect .so
files at runtime:
To ensure compatibility, we attach the same static artifacts as a Lambda Layer:
Layers:
- !Ref LibpqLayer
Environment:
Variables:
LD_LIBRARY_PATH: /opt/lib
PQ_LIB_DIR: /opt/lib
PQ_INCLUDE_DIR: /opt/include/libpq
π§ Lightbulb moment: Build-time and runtime use the exact same files. No duplication. No surprises.
Run the API locally with:
make run-backend
This:
localhost:3000
cargo-watch
Great for development without SAM overhead.
Test your Lambda function locally via Docker:
make aws-run-sam
Visit:
http://localhost:4040/Prod/hello
Deploy your app with:
make aws-deploy-sam
This runs sam deploy
and provisions:
Handler: bootstrap
)GitHub Actions CI runs on push to main
:
make aws-build-sam
make aws-deploy-sam
Test locally with:
act push \
-W .github/workflows/ci.yaml \
--secret-file .env \
-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
cargo-watch
libpq
layer for Diesel and OpenSSLWhy this setup works:
.a
and .h
files power both phasesmusl
, optimized for cold startsπ¦ A solid foundation for production-ready, serverless Rust APIs.
Happy building!