VOOZH about

URL: https://thenewstack.io/rust-and-webassembly-serverless-functions-in-vercel/

⇱ Rust and WebAssembly Serverless Functions in Vercel - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2021-07-27 03:00:21
Rust and WebAssembly Serverless Functions in Vercel
contributed,
Rust / Serverless / Software Development

Rust and WebAssembly Serverless Functions in Vercel

This post will explore how to use WasmEdge functions, written in Rust, to power a Vercel application backend.
Jul 27th, 2021 3:00am by Michael Yuan
👁 Featued image for: Rust and WebAssembly Serverless Functions in Vercel
Feature image via Pixabay.
Michael Yuan
Michael Yuan is the founder and maintainer of WasmEdge, an open-source WebAssembly runtime hosted by the CNCF for edge computing, service mesh, and embedded functions. Dr. Yuan is the author of six books on software engineering, and a long-time open source contributor. He is the co-founder of Second State, a venture-funded startup that supports and commercializes enterprise applications in the WebAssembly and Rust ecosystem.

Vercel is a leading platform for developing and hosting Jamstack applications. Unlike traditional web apps, where the UI is dynamically generated at runtime from a server, a Jamstack application consists of a static UI (in HTML and JavaScript) and a set of serverless functions to support dynamic UI elements via JavaScript.

There are many benefits to the Jamstack approach. But perhaps one of the most significant benefits is performance. Since the UI is no longer generated at runtime from a central server, there is much less load on the server and we can now deploy the UI via edge networks such as CDNs.

However, the edge CDN only solves the problem of distributing the static UI files. The backend serverless functions could still be slow. In fact, popular serverless platforms have well-known performance issues, such as slow cold start, especially for interactive applications. That’s where WebAssembly could help.

With WasmEdge, a cloud native WebAssembly runtime hosted by the Cloud Native Computing Foundation, developers can write high-performance serverless functions deployed on the public cloud or on edge computing nodes. In this article, we will explore how to use WasmEdge functions, written in Rust, to power a Vercel application backend.

Why WebAssembly in Vercel Serverless?

The Vercel platform already has a very easy-to-use serverless framework for deploying functions hosted in Vercel. As we discussed above, the reason to use WebAssembly, and WasmEdge, is to further improve performance. High-performance functions written in C/C++, Rust, and Swift can be easily compiled into WebAssembly. Those WebAssembly functions are much faster than JavaScript or Python commonly used in serverless functions.

However, if raw performance is the only goal, why not just compile those functions to machine native executables? That is because the WebAssembly “container” still provides many valuable services.

For starters, WebAssembly isolates the function at runtime. Bugs or memory safety issues in the code will not propagate out of the WebAssembly runtime. As the software supply chain gets more complex over time, it is important to run code in containers to prevent unauthorized access to your data by dependency libraries.

Second, the WebAssembly bytecode is portable. Developers only need to build it once and do not need to worry about changes or updates to the underlying Vercel serverless container (OS and hardware) in the future. It also allows developers to reuse the same WebAssembly functions in alternative hosting environments, such as in another public cloud such as Tencent Serverless Functions, or in a data streaming framework like YoMo.

Finally, the WasmEdge Tensorflow API provides the most ergonomic way to execute Tensorflow models in the Rust programming language. WasmEdge installs the correct combination of Tensorflow dependency libraries, and provides a unified API for developers.

Enough with the concepts and explanations. Without further ado, let’s jump into the example apps!

Prerequisite

Since our demo WebAssembly functions are written in Rust, you will need a Rust compiler. Make sure that you install the wasm32-wasi compiler target as follows, in order to generate WebAssembly bytecode.

$ rustup target add wasm32-wasi

The demo application front end is written in Next.js, and deployed on Vercel. We will assume that you already have the basic knowledge of how to work with Vercel.

Example 1: Image processing

Our first demo application allows users to upload an image and then invoke a serverless function to turn it into black and white. A live demo deployed on Vercel is available.

👁 Image

Fork the demo application’s GitHub repo to get started. To deploy the application on Vercel, just import the Github repo from Vercel for Github web page.

This repo is a standard Next.js application for the Vercel platform. The backend serverless function is in the api/functions/image_grayscale folder. The src/main.rs file contains the Rust program’s source code. The Rust program reads image data from the STDIN, and then outputs the black-white image to the STDOUT.

use hex;
use std::io::{self, Read};
use image::{ImageOutputFormat, ImageFormat};

fn main() {
 let mut buf = Vec::new();
 io::stdin().read_to_end(&mut buf).unwrap();

 let image_format_detected: ImageFormat = image::guess_format(&buf).unwrap();
 let img = image::load_from_memory(&buf).unwrap();
 let filtered = img.grayscale();
 let mut buf = vec![];
 let format = match image_format_detected {
 ImageFormat::Gif => {
 filtered.write_to(&mut buf, ImageOutputFormat::Gif).unwrap();
 "gif"
 },
 _ => {
 filtered.write_to(&mut buf, ImageOutputFormat::Png).unwrap();
 "png"
 },
 };
 print!("{}{}", format, hex::encode(&buf));
}

You can use Rust’s cargo tool to build the Rust program into WebAssembly bytecode or native code.

$ cd api/functions/image-grayscale/
$ cargo build --release --target wasm32-wasi

Copy the build artifacts to the api folder.

$ cp target/wasm32-wasi/release/grayscale.wasm ../../

Vercel runs api/pre.sh upon setting up the serverless environment. It installs the WasmEdge runtime, and then compiles each WebAssembly bytecode program into a native so library for faster execution.

The api/hello.js file conforms Vercel serverless specification. It loads the WasmEdge runtime, starts the compiled WebAssembly program in WasmEdge, and passes the uploaded image data via STDIN. Notice api/hello.js runs the compiled grayscale.so file generated by api/pre.sh for better performance.

const fs = require('fs');
const { spawn } = require('child_process');
const path = require('path');

module.exports = (req, res) => {
 const wasmedge = spawn(
 path.join(__dirname, 'wasmedge'), 
 [path.join(__dirname, 'grayscale.so')]);

 let d = [];
 wasmedge.stdout.on('data', (data) => {
 d.push(data);
 });

 wasmedge.on('close', (code) => {
 let r = d.join('');
 let format = r.substring(0, 3);
 let buf = Buffer.from(r.substring(3), 'hex');

 res.setHeader('Content-Type', `image/${format}`);
 res.send(buf);
 });

 wasmedge.stdin.write(req.body);
 wasmedge.stdin.end('');
}

That’s it. Deploy the repo to Vercel and you now have a Vercel Jamstack app with a high-performance Rust and WebAssembly based serverless backend.

Example 2: AI inference

The second demo application allows users to upload an image and then invoke a serverless function to classify the main subject on the image.

👁 Image

It is in the same GitHub repo as the previous example but in the tensorflow branch. Note: when you import this GitHub repo on the Vercel website, it will create a preview URL for each branch. The tensorflow branch would have its own deployment URL.

The backend serverless function for image classification is in the api/functions/image-classification folder in the tensorflow branch. The src/main.rs file contains the Rust program’s source code. The Rust program reads image data from the STDIN, and then outputs the text output to the STDOUT. It utilizes the WasmEdge Tensorflow API to run the AI inference.

pub fn main() {
 // Step 1: Load the TFLite model
 let model_data: &[u8] = include_bytes!("models/mobilenet_v1_1.0_224/mobilenet_v1_1.0_224_quant.tflite");
 let labels = include_str!("models/mobilenet_v1_1.0_224/labels_mobilenet_quant_v1_224.txt");

 // Step 2: Read image from STDIN
 let mut buf = Vec::new();
 io::stdin().read_to_end(&mut buf).unwrap();

 // Step 3: Resize the input image for the tensorflow model
 let flat_img = wasmedge_tensorflow_interface::load_jpg_image_to_rgb8(&buf, 224, 224);

 // Step 4: AI inference
 let mut session = wasmedge_tensorflow_interface::Session::new(&model_data, wasmedge_tensorflow_interface::ModelType::TensorFlowLite);
 session.add_input("input", &flat_img, &[1, 224, 224, 3])
 .run();
 let res_vec: Vec<u8> = session.get_output("MobilenetV1/Predictions/Reshape_1");

 // Step 5: Find the food label that responds to the highest probability in res_vec
 // ... ...
 let mut label_lines = labels.lines();
 for _i in 0..max_index {
 label_lines.next();
 }

 // Step 6: Generate the output text
 let class_name = label_lines.next().unwrap().to_string();
 if max_value > 50 {
 println!("It {} a <a href='https://www.google.com/search?q={}'>{}</a> in the picture", confidence.to_string(), class_name, class_name);
 } else {
 println!("It does not appears to be any food item in the picture.");
 }
}

You can use the cargo tool to build the Rust program into WebAssembly bytecode or native code.

$ cd api/functions/image-classification/
$ cargo build --release --target wasm32-wasi

Copy the build artifacts to the api folder.

$ cp target/wasm32-wasi/release/classify.wasm ../../

Again, the api/pre.sh script installs WasmEdge runtime and its Tensorflow dependencies in this application. It also compiles the classify.wasm bytecode program to the classify.so native shared library at the time of deployment.

The api/hello.js file conforms Vercel serverless specification. It loads the WasmEdge runtime, starts the compiled WebAssembly program in WasmEdge, and passes the uploaded image data via STDIN. Notice api/hello.js runs the compiled classify.so file generated by api/pre.sh for better performance.

const fs = require('fs');
const { spawn } = require('child_process');
const path = require('path');

module.exports = (req, res) => {
 const wasmedge = spawn(
 path.join(__dirname, 'wasmedge-tensorflow-lite'),
 [path.join(__dirname, 'classify.so')],
 {env: {'LD_LIBRARY_PATH': __dirname}}
 );

 let d = [];
 wasmedge.stdout.on('data', (data) => {
 d.push(data);
 });

 wasmedge.on('close', (code) => {
 res.setHeader('Content-Type', `text/plain`);
 res.send(d.join(''));
 });

 wasmedge.stdin.write(req.body);
 wasmedge.stdin.end('');
}

You can now deploy your forked repo to Vercel and have a web app for food classification.

What’s Next

Running WasmEdge from Vercel’s current serverless container is an easy way to add high-performance functions to Vercel applications. If you have created an interesting Vercel function using WasmEdge, please let us know and we will send you a WasmEdge SWAG!

Going forward an even better approach is to use WasmEdge as the container itself. There will be no Docker and no Node.JS to bootstrap WasmEdge. This way, we can reach much higher efficiency for running serverless functions. WasmEdge is already compatible with Docker tools. If you are interested in joining WasmEdge and the Cloud Native Computing Foundation for this exciting work, let us know!

TRENDING STORIES
SHARE THIS STORY
TRENDING STORIES
The Cloud Native Computing Foundation is a sponsor of The New Stack.
TNS owner Insight Partners is an investor in: Docker.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.