Is AWS SAM better than Serverless framework? Let's deploy Ruby Telegram Bot with it!

Illustration of a surprised young person looking towards a flying squirrel that is being propelled upwards by a curved orange arrow, with a hat flying off the squirrel's head. Illustration of a surprised young person looking towards a flying squirrel that is being propelled upwards by a curved orange arrow, with a hat flying off the squirrel's head.

A while ago we had a video about Serverless Framework. As a reminder, it’s a set of open source tools to deploy serverless applications on multiple different clouds. We’ve used it to deploy a simple Telegram bot as an AWS Lambda function.

Serverless Framework is great — it has many advanced features, a nice UI and cloud-agnostic abstractions to configure your functions.

But did you know that AWS provides a very similar tool, that offers mostly the same features? It’s called AWS SAM and it will be the topic of this article.

AWS audit: Huge list of AWS services can be intimidating. We'll help you figure it out and choose the right solution for your business. About AWS audits

AWS SAM stands for Serverless Application Model. SAM consists of two things:

  1. A superset of CloudFormation templates, with new, simpler syntax to define serverless components;

  2. A CLI tool, that simplifes building, deploying and maintaing serverless applications

We are going to take Germanizer Telegram Bot and deploy it with AWS SAM. We will also take a look at some of the newer Lambda features, that were not covered in the Serverless Framework video. As a reminder, this bot replies with a German translation of everything we send to it.

I’ve already installed SAM CLI beforehand, you can follow official instructions for your operating system.

I am going to start by running sam init command, to generate some bootstrap code. I will use existing quick start template for the hello world application. My runtime for this app is still Ruby. As for the Package Type, I am going to use Image.

Last time we deployed this app from a zip package, but these days it makes no sense to stick to packaging Lambda’s in archives — we can use industry standard container image packaging.

I can also enable AWS X-Ray tracing in this guided init process.

Project name is going to be germanizer.

init command created for us a new directory with the sample application inside, as well as some tests, so that we can verify our function locally.

I only need 2 files from here:

  1. Dockerfile, which I will rename to be Containerfile;

  2. And template.yaml - the main file that sam CLI is going to use;

I can safely remove everything else, but keep in mind the folder structure that SAM provides is actually not bad when you have multiple functions that form a single serverless application. For my tiny telegram bot, I can get away with a simpler code setup.

Next I need to change Containerfile a bit.

I will change the name of the file with function’s code.

And I will change the command to point to the correct Ruby method.

Now let’s navigate to template.yaml and see what we need to change there. SAM Template is basically a CloudFormation template, with some shorter, serverless-focused resources. You can use any CloudFormation code in this template, and the reverse applies - this template can do only what CLoudFormation is capable of.

I will start with renaming HelloWorld to Germanizer.

Next I am going to remove Events section. Previously, the only way to expose your function over the external HTTP endpoint was to sue APIGateway. This is the way we configured our chatbot the last time. SAM has basically the same syntax to define on which Events the function can be triggered, with “API” type leading to API Gateway configuration.

In 2022, AWS released Lambda Function URL support, meaning that any function can simply get an HTTP URL, and you can trigger the function by sending a request to this URL. There is no more API Gateway involved, and there is also no

Application Load Balancer. It’s perfect for simpler use cases like our primitive chat bot.

Let me configure FunctionUrl in this template. Just two lines of code, specifying that I dont need any authentication, is enough to make my function available over the internet.

Next I am going to specify an environment variable. I will take a telegram bot token from AWS Secrets Manager. I can not use SSM here, because CloudFormation can not resolve secure SSM params.

I also need to change the docker context and the path to the dockerfile.

With those changes, I am ready to build and deploy my function.

I am going to run sam build command.

sam built a new container image. But what it also did, it generated a new SAM template and placed it inside a hidden aws-sam directory. The deployable package for SAM consists of two things:

  1. Container image or ZIP file

  2. Processed SAM template

And when we ran sam build it did both things. Let’s compare the generated template with the original one. It mostly just replaced CloudFormation function calls, but it also added a new ImageUri parameter.

This parameter is used during the deployment to understand from where to get the image to deploy. We could set the ImageUri manually, but let’s rely on automations SAM brings for now.

With the image and template built, I am running sam deploy -g. Guided deployment let’s me set many different options, starting with CloudFormation stack name. I can save answers to all questions to a SAM config file, so that next time I don’t need to go through this process. Notice that I can provide multiple configuration environments, to distinguish between prod and preprod, for example.

It will take a second for SAM to create a special stack for SAM resources. Now I can delegate management of ECR repository to SAM - this option tells SAM to create a new ECR repository and push my function’s image there. It’s convenient to do it this way for demonstration purposes, but for production scenarios you should create and manage ECR repository separately, for example with Terraform.

After pushing the image, SAM will start deploying a new CloudFormation stack with our function and all related resources. Next I need to use the function URL as a webhook endpoint for a Telegram bot. And now I can test the bot!

Strange, I am not getting any answers. Let’s use sam log command to see what's going on.

It seems that I forgot to attach an Amazon Translate policy! Let me do this real quick — I can just specify any managed policy inside Policies field in the template. And now I will build.. and then deploy again.

Let’s try talking to the bot one more time. And now it finally replies in German!

Let’s sum it up.

AWS SAM is a feature complete replacement for Serverless Framework, as long as you only deploy AWS Lambda functions.

Same as Serverless Framework, it’s just a nice abstraction and tooling on top of CloudFormation. The benefit of SAM is that its a solution developed and provided by AWS directly. Also, SAM templates can be more powerful, as they can be any CloudFormation template.

Give it a try! Get the source code here and do this tasks:

  • Change the code to use pre-existing ECR repository;
  • Narrow down IAM permissions to use restricted access to Amazon Translate;
  • Make the template configurable based on environment where you deploy it.

Here's the same article in video form for your convenience: