Hello Serverless Rust

Hello Serverless Rust

Rust is the most-loved language. Many of us most likely professionally work with other languages. For example, I have been doing .NET moving to NodeJS/TypeScript with the serverless movement back in 2015 when the AWS Lambda function was generally available.

Moreover, with time, life brings us to different paths and interests, so time is what it is, and we do have not the "fortune" to stay in front of the computer after work or during the weekends, and this means that we cannot experiment or learn new things as we should.

For me, the pandemic back in March 2020 that forced us to work from home gave me the free time needed. The time I used to have in my early times was now available to me, so I started investing in things more deeply than usual.

My first investment was getting a more profound knowledge of AWS, so I decided to get some certifications (you can read here) and look for a new language to learn and experiment with.

Why Rust?

When we are talking about serverless, speed is essential. Let me be clear here, we are not talking about spending hours of development time saving a few ms, but we are talking about the relation between speed and cost without moving a finger.

As you can see from this image 1634456840046.gif

The most used runtimes are Python and NodeJs. My personal opinion behind this is that they are the two languages supported since the beginning and the most user-friendly and maybe the easiest to pick up for not enterprise applications in the wild. Time has changed, serverless is becoming more prominent, and the relation between speed and cost is becoming more apparent to the mass.

Moreover, AWS has introduced the Sustainability Pillar,

Figure-1.-Shared-responsibility-model-for-sustainability.jpg

We, developers or companies, also need to do our part, so Rust is perfect for the job.

Mac Configuration

Let's install Rust:

brew install rustup

After this:

rustup-init

And select option 1, and once it is finished, you should be able to see the version. In my case

rustc -V
rustc 1.57.0 (f1edd0429 2021-11-29)

I am using VS Code, and we need enabling Rust we need to install:

Now from the terminal of VSCode

cargo --version
cargo 1.57.0 (b2e52d7ca 2021-10-21)

Now we have installed all, and you can create your project with

cargo new ServerlessHelloWorld

Once you remove this warning:

snake.png

To add dependencies we can install cargo-edit.

Currently available subcommands:

  • cargo add
  • cargo rm
  • cargo upgrade
  • cargo set-version

For example, now we can do this:

cargo add lambda_runtime

Lambda function

Now you are ready to start to write your first Serverless Rust Lambda function. The skeleton of a Lambda is the following:

#[tokio::main]
async fn main() -> Result<(), Error> {
  // Initialize services in the Lambda Execution Context 
  // Load logger
  // Load AWS services

  lambda_runtime::run(handler_fn(|event: SqsEvent, ctx: Context| {
        execute(&aws_client, event, ctx)
    })) 
    .await?;

  Ok(())
}

pub async fn execute(client: &AWSClient, event: SqsEvent, _ctx: Context) -> Result<(), Error> {
  log::info!("EVENT {:?}", event);
  // Your code here

  Ok(())
}

Complete example on GitHub.

Let me explain to you the template.

#[tokio::main]

Tokio is an event-driven, non-blocking I/O platform for writing asynchronous applications with the Rust programming language, and it is needed to mark the entry point async.

// Initialize services in the Lambda Execution Context

When Lambda service call your function, an execution environment is created. As your lambda function can be invoked multiple times, the execution context is maintained for some time in anticipation of another Lambda function invocation. When that happens, it can "reuse" the context, and the best practice is to use it to initialize your classes, SDK clients and database connections outside. This saves execution time and cost for subsequent invocations (Warm start).

pub async fn execute(client: &AWSClient, event: SqsEvent, _ctx: Context) -> Result<(), Error> {

It is where your logic will be, and as you can see, I pass my pre-initialized module called AWSClient.

Conclusion

Rust is not wildly adopted in the serverless world, and a lot must be done by third parties (SaaS platforms) to make the usage at an enterprise level. As people used to say about Serverless, it costs more or is slower or too complicated. The same is for Rust because it is not just for OS, CLI-tools, graphics, or low-level needs. It can be used at a higher level for serverless applications that bring out of the box speed not achievable with Python, NodeJs or others. The code and concepts could be more difficult for some, but it is a programming language like others, so you get used soon. Speed in a world hyperconnected where everything must be available in real-time is essential, and for few that use this concept at scale, it will result in a cheaper cloud cost.