paint-brush
How Using AWS Lambda with Rust Saved 3x the Cost Compared to Using Python or .NETby@niro
5,215 reads
5,215 reads

How Using AWS Lambda with Rust Saved 3x the Cost Compared to Using Python or .NET

by Niro A3mMarch 7th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Do you keep reading articales on golang and rust and wander if its worth using them as a programming language ? Do you use serverless / FaaS ? Ever wander what AWS Lambda with rust would be like ? This is the journey for you!

Coin Mentioned

Mention Thumbnail
featured image - How Using AWS Lambda with Rust Saved 3x the Cost Compared to Using Python or .NET
Niro A HackerNoon profile picture

With AWS Lambda and FaaS, squeezing every ounce of performance to reduce cost and improve user experience can be important. While adopting Rust is not a decision that should be made lightly for mature organizations if it's not a skill that exists already— this is my journey writing one and learning Rust the hard way to prove its value.

Goal

  • API Gateway Custom Authorizer in Rust
  • Validate JWT tokens
  • Support a multi-tenant architecture
  • Generate session credentials for an assumed role within the Authorizer for tenant isolation and to make use of API Gateways cache
  • Get execution time as low as possible

The final code for all the lambda functions can be found on GitHub here:

RustPythonDotnet6

At this point, I assume you know AWS Lambda and Rust, see further links at the bottom for help getting started!

Rust, Lambda, and trying to create static objects on initialization

Coming from C#/Java/Python/etc, it took me a while to figure out how to create static objects to ensure we are not repeating code/processing inside the lambda handler function.

This is what it ended up looking like:

The idea here is that the Valid Issuer list and JWK list are only parsed once from the Lambda environment variable.

If the auth provider supports key rotation the assumption is that would be a manual step to update the Lambda environment variables. While its obviously good policy to perform key rotation, supporting that automatically means looking at performing a web request to retrieve JWK’s from Cognito and ensuring that we are safe from JWK attacks where the caller rotates the kid to force refreshing every time, etc (leaving this for another day).

Authorizer Flow

Implementing this code in Rust as below:

Validating the token

Validation is done using a fairly popular Rust crate called jsonwebtoken, and for what it's worth, some validation was done by jwt.io at https://jwt.io/libraries.

For this implementation, I went with validating:

  • the issuer
  • expiry time
  • signature

Future steps could be to look at the audience, etc. The code snippet is below:


Performance Testing

Method

Using Artillery, short bursts of up to 100 requests per second, the values below represent the 99th percentile for each runtime

In each case, the focus has been spent making the function code as efficient as possible, feedback is always welcome! (Please raise any improvements on GitHub).

Results

256mb Memory allocated.

TBD -> Golang,nodejs,java and testing on 512/1024mb.

Cost-benefit

Scenario

Assuming the authorizer is fronting a system that has constant use and spikes are negligible (to cost), at 1 million unique login/tokens a day (rest would be cached) -> 31 million a month.

Rust -> $9.30/month

Python -> $35.27/month

Dotnet -> $29.58/month

Final thoughts

It wasn't easy for me to adopt Rust coming from higher-level languages, but looking at the results of building for large-scale use, then it certainly feels worth it both from a cost perspective (factor x3 saved) and from a performance perspective.

It doesn't feel like purely looking at a Lambda Authorizer as a use case provides enough clarity on any potential benefits, so watch out for part 2 where we look at a backend with real-world functionality to test out if language plays a big part in cost/performance on the AWS Lambda platform.

Helpful Links

The AWS repositories below provide some great guidance on how to start with Rust + AWS Lambda:

The links below provide some great starting points for an API Gateway Authorizer: