| Crates.io | lambda-grpc-web |
| lib.rs | lambda-grpc-web |
| version | 0.1.1 |
| created_at | 2026-01-06 10:23:51.606854+00 |
| updated_at | 2026-01-07 03:34:12.357556+00 |
| description | grpc-web framed tonic service adaptor to aws lambda runtime |
| homepage | |
| repository | https://github.com/zakhenry/lambda-grpc-web |
| max_upload_size | |
| id | 2025552 |
| size | 53,454 |
Run Tonic gRPC services on AWS Lambda.
This crate makes gRPC usable on AWS Lambda, with grpc-web message framing as lambda-compatible http/1.1 transport.
This enables serverless deployments for gRPC workloads that are spiky, generally low volume (i.e. benefit from being able to need to scale to zero), and typically are connect to from web browsers (i.e. already limited to using gRPC web protocol)
[!IMPORTANT] This is not a full replacement for a native http/2 gRPC server. Limitations inherent to the AWS lambda runtime apply See below for more detail of supported capabilities
Define a normal Tonic service, and substitute only the tonic::transport::Server builder with lambda_grpc_web::LambdaServer
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
use lambda_grpc_web::lambda_runtime::Error;
use lambda_grpc_web::LambdaServer;
use tonic::{Request, Response, Status};
// note everything from here until the main fn is vanilla tonic service
pub mod hello_world {
tonic::include_proto!("helloworld");
}
#[derive(Debug, Default)]
pub struct MyGreeter {}
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>,
) -> Result<Response<HelloReply>, Status> {
println!("Got a request: {:?}", request);
let reply = HelloReply {
message: format!("Hello {}!", request.into_inner().name),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Error> { // <- note error here is `lambda_grpc_web::lambda_runtime::Error`
let greeter = MyGreeter::default();
LambdaServer::builder() // <- Different builder
.add_service(GreeterServer::new(greeter))
.serve() // <- no socket declared
.await?;
Ok(())
}
Refer to https://cargo-lambda.info for more information
cargo lambda watch
Important note - the grpc service frames messages with grpc-web - your test client must be able to talk this protocol.
Compile with cargo lambda (refer to their docs)
[!TIP]
- Make sure to configure invoke mode as
RESPONSE_STREAM- Configure a sensible timeout as client disconnects cannot propagate to lambda cancellation.
| Feature | Status | Note |
|---|---|---|
| Unary RPCs | Supported | |
| Server streaming | Limited | Capped by lambda timeout |
| Client streaming | Not supported | Not supported in gRPC web |
| Bidirectional streaming | Not supported | Not supported in gRPC web |
| Interceptors / Tower layers | Supported | |
| Metadata (Headers+Trailers) | Supported |
Since this is a serverless environment, it is subject to cold start times. While Rust runtime is very fast (typically 20-30ms), it is not going to be as fast as a standard always-running gRPC service on ECS or similar.
When executing on a warm instance, latency should be very low albeit with minor overhead from the grpc-web framing.
If maximum performance is your goal, gRPC might not be the best fit to begin with. For nearly all other workloads, this architecture will be more than fast enough.