| Crates.io | lambda-simulator |
| lib.rs | lambda-simulator |
| version | 0.1.5 |
| created_at | 2025-12-07 12:16:28.354001+00 |
| updated_at | 2026-01-06 13:46:31.664429+00 |
| description | High-fidelity AWS Lambda Runtime API simulator for testing Lambda runtimes and extensions locally |
| homepage | |
| repository | https://github.com/djvcom/lambda-observability |
| max_upload_size | |
| id | 1971500 |
| size | 4,009,669 |
High-fidelity AWS Lambda Runtime API simulator for testing Lambda runtimes and extensions locally.

The simulator reproduces real Lambda behaviour including process freeze/thaw using SIGSTOP/SIGCONT signals. Run the demo yourself:
cargo build --workspace
cargo test -p lambda-simulator --test freeze_demo_test -- --nocapture --ignored
This crate provides a simulator that implements the AWS Lambda Runtime API, Extensions API, and Telemetry API, allowing you to test Lambda runtimes and extensions without deploying to AWS. It's particularly useful for:
/runtime/invocation/next, response/error endpoints)[dev-dependencies]
lambda-simulator = "0.1.0"
Minimum Supported Rust Version (MSRV): 1.91.1
use lambda_simulator::{Simulator, InvocationBuilder};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a simulator
let simulator = Simulator::builder()
.function_name("my-test-function")
.build()
.await?;
// Get the Runtime API URL for your runtime
let runtime_api = simulator.runtime_api_url();
println!("Runtime API available at: {}", runtime_api);
// Enqueue an invocation
simulator.enqueue_payload(json!({
"message": "Hello, Lambda!"
})).await;
// Your runtime connects to runtime_api and processes the invocation
Ok(())
}
The simulator provides efficient, event-driven wait helpers:
use lambda_simulator::{Simulator, InvocationStatus};
use serde_json::json;
use std::time::Duration;
#[tokio::test]
async fn test_my_runtime() {
let simulator = Simulator::builder()
.function_name("test-function")
.build()
.await
.unwrap();
// Set the runtime API URL for your runtime
std::env::set_var("AWS_LAMBDA_RUNTIME_API", simulator.runtime_api_url());
// Enqueue returns the request ID for tracking
let request_id = simulator.enqueue_payload(json!({"key": "value"})).await;
// Start your runtime in a background task
// tokio::spawn(async { my_runtime::run().await });
// Wait for completion with timeout - no polling loops needed
let state = simulator
.wait_for_invocation_complete(&request_id, Duration::from_secs(5))
.await
.expect("Invocation should complete");
assert_eq!(state.status, InvocationStatus::Success);
}
use lambda_simulator::Simulator;
use std::time::Duration;
#[tokio::test]
async fn test_extension_registration() {
let simulator = Simulator::builder().build().await.unwrap();
// Start your extension pointing at the simulator
std::env::set_var("AWS_LAMBDA_RUNTIME_API", simulator.runtime_api_url());
// tokio::spawn(async { my_extension::run().await });
// Wait for extension to register
simulator.wait_for(
|| async { simulator.extension_count().await >= 1 },
Duration::from_secs(5)
).await.unwrap();
// Verify registration
let extensions = simulator.get_registered_extensions().await;
assert_eq!(extensions.len(), 1);
}
Capture telemetry events in memory for assertions:
use lambda_simulator::Simulator;
use serde_json::json;
#[tokio::test]
async fn test_telemetry_events() {
let simulator = Simulator::builder().build().await.unwrap();
// Enable in-memory capture
simulator.enable_telemetry_capture().await;
// Process invocations...
simulator.enqueue_payload(json!({"test": "data"})).await;
// Assert on captured events
let events = simulator.get_telemetry_events_by_type("platform.initStart").await;
assert!(!events.is_empty());
}
Simulate Lambda's freeze/thaw behaviour:
use lambda_simulator::{Simulator, FreezeMode};
let simulator = Simulator::builder()
.freeze_mode(FreezeMode::Process)
.build()
.await?;
// Register PIDs to freeze between invocations
simulator.register_pid_for_freeze(extension_pid).await;
// Processes are frozen after invocation completes
// and unfrozen when the next invocation arrives
| Endpoint | Status |
|---|---|
GET /runtime/invocation/next |
✅ |
POST /runtime/invocation/{id}/response |
✅ |
POST /runtime/invocation/{id}/error |
✅ |
POST /runtime/init/error |
✅ |
| Endpoint | Status |
|---|---|
POST /extension/register |
✅ |
GET /extension/event/next |
✅ |
POST /extension/init/error |
✅ |
POST /extension/exit/error |
✅ |
| Endpoint | Status |
|---|---|
PUT /telemetry |
✅ |
| Feature | Linux | macOS | Windows |
|---|---|---|---|
| Runtime API | ✅ | ✅ | ✅ |
| Extensions API | ✅ | ✅ | ✅ |
| Telemetry API | ✅ | ✅ | ✅ |
| Process Freezing | ✅ | ✅ | ❌ |
Process freezing uses POSIX signals (SIGSTOP/SIGCONT) and is not available on Windows.
This simulator is designed for testing and development. Some AWS Lambda behaviours are not yet fully simulated:
Lambda-Runtime-Deadline-Ms header is set correctly, but invocations are not automatically terminated when they exceed their timeoutThese limitations don't affect most testing scenarios, but be aware of them when validating timeout handling or resource limits.
MIT