GitHub

Benchmark comparing Python and Rust AWS Lambda performance on an identical, realistic workload: read a file from S3, parse it, and batch-write 50,000 event registration records to DynamoDB — with real-time progress streamed to the browser over a WebSocket API.

This is the source code for the blog post "We Cut Our Lambda Bill by 33% Switching to Rust — And AI Wrote the Code".

What it measures

  • 50,000 event registration records across 30 music concerts, 11 fields each
  • Stored in S3 as both CSV (7.8 MB) and JSON (17.1 MB)
  • Identical config for both runtimes: 1024 MB, ARM64/Graviton, on-demand DynamoDB, batch writes of 25 with retry
  • Only difference: Python 3.12 managed runtime vs Rust on provided.al2023
  • A verification Lambda confirms both tables contain identical data after each run
Browser (WebSocket) → API Gateway → Lambda → S3 + DynamoDB
                    ← progress messages ←

Layout

cdk/        AWS CDK stack (Python) — defines Lambdas, DynamoDB, S3, WebSocket API
data/       generate_data.py — produces the CSV/JSON test data (not committed)
lambdas/
  python_processor/   Python 3.12 handler
  rust_processor/     Rust handler (cargo-lambda, provided.al2023)
  verify/             confirms both tables match
  configure/          runtime wiring
ui/         static dashboard (WebSocket client) served locally

Reproduce

# Prerequisites
rustup install stable
brew install zig            # for cross-compilation
cargo install cargo-lambda
# Build the Rust Lambda
cd lambdas/rust_processor
cargo lambda build --release --arm64
# Generate test data
python data/generate_data.py
# Deploy
cd cdk
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cdk deploy --outputs-file outputs.json
# Wire the UI to your deployed WebSocket URL
node update_config.js        # writes ui/config.js from cdk/outputs.json
# Run the UI
cd ui && python -m http.server 8080

Open http://localhost:8080, click Warm Up, then Run All Tests. Watch the progress stream in real time, then click Verify Data to confirm both tables match.

Note: cdk/outputs.json and ui/config.js hold the WebSocket URL for your deployment and are git-ignored. Copy ui/config.example.js to ui/config.js if you want to point the UI at an existing endpoint by hand.

Results (warm, 50k records)

Test Total time Parse Avg / 1k records
Rust + CSV 14,740 ms 140 ms 295 ms
Rust + JSON 12,416 ms 167 ms 248 ms
Python + CSV 21,194 ms 469 ms 424 ms
Python + JSON 20,205 ms 170 ms 404 ms

Rust runs ~33% faster on this workload. The gap is bounded by DynamoDB write I/O rather than CPU; pure-compute workloads would favour Rust by a wider margin.

Read the original on github.com ↗