Replacing FastAPI with Rust: Part 6 - AWS Lambda
Cover image created by me using Ferris the Crab, the Rust logo, and the FastAPI logo.
This post is part of a series. If you haven’t already, you may want to read the previous post before continuing.
The last blog post was a bit long, so I figured I’d take a bit of a break and tackle a shorter topic. In this post, we’ll take a look at two different methods to deploy our Rocket application to AWS Lambda: the SAM CLI and AWS CDK.
Prerequisites
If you want to follow any of the instructions below, you’ll first need an AWS account to experiment on. I did this on an account where the free tier has already expired and I didn’t accumulate any charges so you should be able to do this for free, but I make no guarantees.
Once you have your account set up, you’ll need to generate some IAM credentials, install the AWS CLI, and configure it to use your credentials.
SAM CLI
If you’ve followed along with previous posts, you’ll know that I’ve been using the SAM CLI in order to test the application locally. This allows me to emulate the AWS environment for testing, which is invaluable, but it’s not the only purpose of the tool. It can also be used to build and deploy the application to AWS.
To start off, you’ll need to do a sam build
before each deploy, just like was necessary before doing a sam local start-api
to run locally. If you’ve run this before with the same settings I have in the experiments repo, you’ll know that it feels like it takes forever because you get no feedback on the build process. There might be a way to fix this, but I haven’t found it yet.
After the app is finish building, you’ll want to do a sam deploy --profile <aws_profile_name> --guided
(omit the --profile
if you’ve only got one AWS profile configured) and follow the prompts. This will create a samconfig.toml
file with some additional required information for SAM. In the future, to redeploy, you can omit the --guided
because you already have this file. Now feels like a good time to note that if you’ve copied the template.yml
from my repo previously, you’ll want to update it from the one in the SAM experiments branch because it was missing a required attribute previously.
The sam deploy
command is going to deploy, it’s that easy! Answer any questions it has and wait for it to be done. Now you’ve got an API Gateway URL you can hit to talk to your API in the cloud! But wait… where’s the URL?
I had to do quite a lot of digging to figure out where to call my freshly hosted API. Eventually I found these docs which informed me the url should be something like https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}/
. The {restapi_id}
is replaced with an ID I found in the API Gateway console, {region}
is what I configured with sam deploy --guided
, and {stage_name}
appears to be Prod
by default.
With that URL, I was able to test out my API and verify that everything was working. Now it was time to tear down that test infrastructure, so it didn’t sit there in my account now that it was unneeded. Unfortunately there doesn’t seem to be a sam
command for that, so I had to go into the CloudFormation console and tell it to delete everything for me. There was one slight snag with that as I had to find the S3 bucket it created and empty it myself before it would delete.
Overall the sam
experience was fairly painless. I’d say the toughest part was figuring out which URL to call once everything was deployed.
AWS CDK
AWS CDK is a tool that allows you to define your AWS infrastructure in a programming language instead of using CloudFormation syntax (e.g. in template.yml
for sam
). The languages available listed in the docs are TypeScript, JavaScript, Java, Python, and C#. The CLI tool also seems to indicate that F# is an option, so that might be worth looking into if it interests you. I went with TypeScript for this project because:
- It’s a language I know.
- It’s strongly, statically typed.
- The CDK CLI requires
node
anyway.
Before I walk through how I got to a working solution (as it was fairly difficult to piece together all the answers), feel free to take a look at the CDK branch of the experiments repo to see the result for yourself. The relevant bits are:
- The
Makefile
which contains rules for building and deploying via CDK - The various
.json
files which configure the Node/TypeScript things - The
cdk
directory which contains the actual infrastructure code
Here’s the high level process I followed to get there:
- Follow these instructions to install CDK.
- Create a directory to keep your infrastructure code in and initialize it with cdk. I did
mkdir cdk && cd cdk && cdk init app --language typescript
. - Delete the TypeScript handler code since we won’t be needing that.
- Follow these instructions to add the necessary components for Lambda and API Gateway.
- Take some inspiration from this blog post for setting up Rust builds with CDK.
- Find and use
apigateway.LambdaRestApi
in CDK to make the infrastructure setup way simpler.
With the CDK code all set up correctly, the steps to deploy are:
cdk bootstrap --profile <aws_profile>
to set up some basic infrastructure (you only have to do this once).- Run
make deploy
which builds the binary, copies it into a new folder and names it “bootstrap”, then runscdk deploy
. CDK has been configured to upload this folder to Lambda to use as a runtime.
The solution is very nice once you put all the pieces together. I strongly recommend copying most of what I have if you’re going with a straight proxy (all requests from API Gateway go to one lambda handler). The clear benefits over SAM are:
- Using a typed language instead of YAML means you get autocompletion and don’t have to fumble around as much through documentation to find what you’re looking for.
- Using normal
cargo build
then copying over the binary means you get normal cargo outputs instead of a blank screen while building. - CDK comes with a nice
cdk destroy
command which will tear down most of what it created (just not the bootstrap stuff). - It’s easy to break up your code into reusable components. You can even create normal packages with whatever language you selected and share those to other projects, so you don’t have to copy/paste infrastructure. I’ll definitely be doing this in the future.
The only question left to answer was how to run the function locally. Luckily AWS provides official and easy instructions for running a CDK function using SAM, and it works super easily! In my repo, I can do make local
which basically builds the app, runs cdk synth > template.yaml
, then runs the same sam local start-api
I was already doing.
There is another option for running locally which you can try, but I had very little success with it. There is a project called LocalStack for emulating AWS services via Docker containers. I’ve used it in the past for doing integration tests with SQS, however their API Gateway support is pretty atrocious. You have to dig around in their docs for a while to find the long, custom URL you need to call which requires copying and pasting the API ID every time. All the effort didn’t seem worth it to me, but if you want to try it out yourself I found this GitHub repo which should get you started in the right direction.
Conclusion
AWS CDK definitely seems like a great option for deploying functions, as well as managing any other infrastructure you need (like maybe an RDS database?). The only real downside is that you have to add yet another tool on top of SAM and a bunch of dependencies for whatever language you choose to write in. Too bad there’s no Rust CDK option… yet.
Was this post super helpful to you? Tip me on GitHub, Patreon, or Ko-Fi.
Have a question or comment about this post? Leave it in the discussion thread on GitHub!
Want to be notified of future posts? Watch releases in the GitHub repo or follow me on Mastodon
Have an idea or request for a future blog topic? Drop it in the GitHub discussions under ideas.