Why I Converted an AWS SAM Template to Serverless

August 6, 2019

Using the serverless framework reduced deployment complexity by 97.4%.

Words

Serverless here refers to application components with little to no IT overhead so you can focus on your main logic.

SAM is the Serverless Application Model. It’s an AWS abstraction over AWS CloudFormation that makes common serverless architectures easier to define.

The Serverless Framework is an open-source project maintained by Serverless that not only makes it easier to define but also deploy serverless.

A Serverless Guru is someone who works at Serverless Guru, such as yours truly.

Why convert from SAM? Why not start from scratch?

Converting from SAM to the serverless framework only requires a couple of lines of code changes. So why not take advantage of all those great open-source ideas on GitHub by organizations like AWS Labs and the benefits of the Serverless Framework at the same time?

What did you mean by 97.4%?

Here are the four steps to deploy an API using SAM:

  
aws s3 mb s3://java-springboot-test-with-sam
aws cloudformation package --template-file sam.yaml --output-template-file output-sam.yaml --s3-bucket java-springboot-test-with-sam
aws cloudformation deploy --template-file output-sam.yaml --stack-name ServerlessSpringBootSample --capabilities CAPABILITY_IAM
aws cloudformation describe-stacks --stack-name ServerlessSpringBootSample
  

Here’s that with the Serverless Framework:

  
sls deploy
  

So in terms of the number of characters you would need to type to deploy the API using the command line, the serverless framework requires 97.4% less.

Aliases and Installing the CLIs

By the way, sam package and sam deploy are aliases for aws cloudformation package and aws cloudformation deploy. sam requires an additional install.

And sls is an alias for serverless. To use both it’s one install.

Can I deploy to multiple stages from a single template?

With sls you can. With SAM you can’t.

If you want to be able to deploy to a dev environment when running sls deploy and to prod when running sls deploy -s prod, just add a stage option in the provider block:

  
provider:
  stage: ${opt:stage, 'dev'}
  

How do I add default values, like regions? 🌍

You can’t in a SAM.yaml, but you can set your local computer’s CLI’s default region. For example, if you deploy most often to AWS GovCloud (US-East), you can run the following:

  
aws configure --region us-gov-east-1
  

With sls, however, you can set a default region for a template. If you want to be able to deploy to the home of Serverless Guru, Oregon, when running sls deploy and to AWS’s newest region Bahrain when running sls deploy -r me-south-1, just add a stage option in the provider block:

  
provider:
  region: ${opt:region, 'us-west-2'}
  

And custom variables?

The serverless framework even supports as many different custom variables as you want! You can add a variable called turtleName under the section custom and then reference that with${self:custom.turtleName}. 🐢

The best you’ll get with SAM is intrinsic functions like Fn::Sub.

How did you convert from SAM to SLS?

Delete this:

  
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

# The Serverless Framework outputs the URL automatically, 
# minus the `/pets` in Outputs.SpringBootPetStoreApi.Value:
Outputs:
  SpringBootPetStoreApi:
    Description: URL for application
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/pets'
    Export:
      Name: SpringBootPetStoreApi
  

Because the serverless framework is all about Lambdas, it already knows you want the baseline permissions. So, delete this:

  
Policies: AWSLambdaBasicExecutionRole
  

This example is for an API with Java Spring Boot. To avoid the Serverless Error, “No petstore.zip file found in the package path you provided,” add this bit:

  
package:
  individually: true
  

Translations (from SAM to sls):

Type: AWS::Serverless::Function ➡️ functions:

Globals.Api.EndpointConfiguration: REGIONAL ➡️ provider.endpointType: REGIONAL

  
Events:
  GetResource:
    Type: Api
    Properties:
  

🔽

  
events:
  

Please show me the whole thing, side by side

The SAM version, without stage and region defaults:

  
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example Pet Store API written with SpringBoot with the aws-serverless-java-container library

Globals:
  Api:
    # API Gateway regional endpoints
    EndpointConfiguration: REGIONAL

Resources:
  PetStoreFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.amazonaws.serverless.sample.springboot.StreamLambdaHandler::handleRequest
      Runtime: java8
      CodeUri: target/serverless-spring-boot-example-1.0-SNAPSHOT-lambda-package.zip
      MemorySize: 1512
      Policies: AWSLambdaBasicExecutionRole
      Timeout: 60
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: any

Outputs:
  SpringBootPetStoreApi:
    Description: URL for application
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/pets'
    Export:
      Name: SpringBootPetStoreApi
  

The Serverless Framework version, with stage and region defaults:

  
service: petstore

provider:
  name: aws
  runtime: java8
  memorySize: 1512
  timeout: 60
  stage: ${opt:stage,'dev'}
  region: ${opt:region, 'us-west-2'}
  profile: ${opt:profile, "default"}
  endpointType: REGIONAL

resources:
  Description: Example Pet Store API written with SpringBoot with the aws-serverless-java-container library

package:
  individually: true

functions:
  SpringBootPetStoreApi:
    package: 
      artifact: target/serverless-spring-boot-example-1.0-SNAPSHOT-lambda-package.zip
    handler: com.amazonaws.serverless.sample.springboot.StreamLambdaHandler::handleRequest
    events:
      - http:
          path: /{proxy+}
          method: ANY
  

Not counting the bonus region, stage, and profile options, that you don’t get with SAM, the serverless.yml has 32% fewer characters.

Deployment commands can be reduced by 97% and templates by 32% when you use the serverless framework.

I tried it the SAM way, and I got this weird file on S3…

When you run sam package, your application code will show up on S3 as a file named with a long string of random characters.

Download that strange file, and no application can open it.

Add .gzip as the file extension, and then you’ll be able to open it. 🛫

I want to convert Java Lambdas with you! Where do I go?

We forked the Serverless Java container project from aws-labs and converted the Spring Boot sample from SAM to sls. If you’d like to convert some of the others, be our guest and submit a PR.

***A couple of friendly AWS folks commented that it may be useful to readers, to mention CloudFormation parameters, and how they can be used to achieve the same effect as Serverless Framework variables and stages.

Serverless Handbook
Access free book

The dream team

At Serverless Guru, we're a collective of proactive solution finders. We prioritize genuineness, forward-thinking vision, and above all, we commit to diligently serving our members each and every day.

See open positions

Looking for skilled architects & developers?

Join businesses around the globe that trust our services. Let's start your serverless journey. Get in touch today!
Ryan Jones - Founder
Ryan Jones
Founder
Speak to a Guru
arrow
Edu Marcos - CTO
Edu Marcos
Chief Technology Officer
Speak to a Guru
arrow
Mason Toberny
Mason Toberny
Head of Enterprise Accounts
Speak to a Guru
arrow

Join the Community

Gather, share, and learn about AWS and serverless with enthusiasts worldwide in our open and free community.