Write Netlify Functions in Rust

By Eduardo Bouças Published in News & Announcements on October 14, 2021

Netlify Functions give developers an unrivalled workflow for building the backend of a web application, allowing them to focus on writing the business logic instead of provisioning servers, orchestrating deployments, or navigating verbose configuration.

With an integrated local development experience, it’s possible to make changes to functions with a very short feedback loop, with compilation or build steps taken care of automatically behind the scenes. Developers can even generate a public URL for their local server, allowing colleagues or clients to follow along wherever they are in the world.

Currently, this complete experience is available for JavaScript, TypeScript, and Go functions. Today, we’re excited to announce experimental support for Rust in the Netlify Functions offering.

Enabling the feature

During the experimental period, support for Rust must be enabled on a per-site basis by setting the NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE environment variable to true. You can do this in the Netlify UI by going to Site settings > Build & deploy > Environment, or using the CLI:

netlify env:set NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE true

Creating a function

To create a new Rust function, you can run cargo init FUNCTION_NAME from your configured functions directory.

The name you choose for the function determines its endpoint. For example, running cargo init hello will create a function which, when deployed, will be accessible on the /.netlify/functions/hello endpoint.

Alternatively, you can get a jump-start with the Netlify CLI’s function generator. Run netlify functions:create --language=rust, choose a template, and you’ll get a fully working function, ready to be deployed and modified to fit your needs.

(You’ll need Netlify CLI version 6.12.0 or later. Run npm i -g netlify-cli to install the latest.)

Function structure

Every function must include a handler that receives requests and returns responses. This takes shape as a function using the ApiGatewayProxyRequest and ApiGatewayProxyResponse types from the aws_lambda_events crate.

Below is an example of a Rust function that returns a message saying “Hello world”.

use aws_lambda_events::event::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse};
use aws_lambda_events::encodings::Body;
use http::header::HeaderMap;
use lambda_runtime::{handler_fn, Context, Error};
use log::LevelFilter;
use simple_logger::SimpleLogger; #[tokio::main]
async fn main() -> Result<(), Error> { SimpleLogger::new().with_level(LevelFilter::Info).init().unwrap(); let func = handler_fn(my_handler); lambda_runtime::run(func).await?; Ok(())
} pub(crate) async fn my_handler(event: ApiGatewayProxyRequest, _ctx: Context) -> Result<ApiGatewayProxyResponse, Error> { let path = event.path.unwrap(); let resp = ApiGatewayProxyResponse { status_code: 200, headers: HeaderMap::new(), multi_value_headers: HeaderMap::new(), body: Some(Body::Text("Hello world".to_owned())), is_base64_encoded: Some(false), }; Ok(resp)
}

To try this function, you can clone the GitHub repository, or deploy it directly to your Netlify account using the button below.

Deploy to Netlify

Local development

You can use Netlify Dev to test your functions locally. Run netlify dev and open http://localhost:8888/.netlify/functions/hello in the browser. If you’d like to generate a public URL that is accessible from anywhere, use netlify dev --live.

Your function will be rebuilt automatically every time you change a file, so that you and your colleagues can see the changes immediately.

Deployment

Once you’re happy with your changes, you can commit and push the files to Git. We’ll take care of building and deploying your functions automatically.

Our build system runs cargo build --release under the hood. If you’d like to customize the build pipeline, you can do so by specifying a build command that builds the functions and places the binaries in the configured functions directory. If you do that, make sure to use x86_64-unknown-linux-musl as the build target.

Deploying a function for the first time may take a few minutes, since compiling a binary for release is a time-consuming process. But the build artefacts are cached between builds, so subsequent deploys should be significantly faster.

Lab goggles required

This feature may change substantially while we fine-tune the implementation. Still, in the spirit of involving our customers in the development of the product, we’re excited to get it in front of you sooner rather than later. Your feedback will help us create the best possible experience for everyone using Netlify.

Happy builds, fellow Rustaceans! 🦀 🥽