Serverless Functions in Rust on AWS Lambda: A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Rust is the Ideal Language for Serverless



Serverless architecture has become the standard for modern cloud applications. However, classic languages (Python, Node.js) often suffer from slow cold starts and high memory consumption. Rust solves these problems: its compiled binaries start in milliseconds, and memory consumption is minimal. In this article, we will cover how to create, deploy, and optimize AWS Lambda functions in Rust — from environment setup to production deployment.



1. Environment and Tools Setup



Installing Rust and Cargo Lambda

To work with AWS Lambda in Rust, you will need:

  • Rust (install via rustup)
  • Cargo Lambda — the official tool for building and deploying
  • AWS CLI with configured credentials


# Installing Rustcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Installing Cargo Lambdacargo install cargo-lambda

# Verificationcargo lambda --version


Creating a New Project

Cargo Lambda automatically generates a template with Lambda Runtime API support:



cargo lambda new my-rust-lambdacd my-rust-lambda


The project structure includes Cargo.toml with lambda_runtime and serde dependencies, as well as a src/main.rs file with a basic handler function.



2. Writing Your First Serverless Function in Rust



Basic Handler Structure

Let's look at a simple Lambda function that accepts JSON with a name and returns a greeting:



use lambda_runtime::{service_fn, LambdaEvent, Error};use serde::{Deserialize, Serialize};

#[derive(Deserialize)]struct Request { name: String,}

#[derive(Serialize)]struct Response { message: String, request_id: String,}

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> { let req = event.payload; let resp = Response { message: format!("Hello, {}! You are on Rust!", req.name), request_id: event.context.request_id, }; Ok(resp)}

#[tokio::main]async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await}


Key points:

  • service_fn wraps an async function into a handler
  • LambdaEvent contains the payload and context (request_id, deadline, etc.)
  • Serialization/deserialization via serde


Local Testing

Before deployment, let's test the function locally:



cargo lambda watch# In another terminal:cargo lambda invoke --data-ascii '{"name": "World"}'


You should receive a response: {"message":"Hello, World! You are on Rust!","request_id":"..."}



3. Working with AWS Services (S3, DynamoDB)



Integration with S3 via AWS SDK

Add to Cargo.toml:



[dependencies]aws-sdk-s3 = "1.0"aws-config = "1.0"


Example function that reads an object from S3:



use aws_sdk_s3::Client;

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> { let config = aws_config::load_from_env().await; let s3_client = Client::new(&config);

let bucket = "my-bucket"; let key = &event.payload.name;

let object = s3_client .get_object() .bucket(bucket) .key(key) .send() .await?;

let body = object.body.collect().await?; let content = String::from_utf8(body.to_vec())?;

Ok(Response { message: format!("File content: {}", content), request_id: event.context.request_id, })}


In

Blogs

Book Recommendations