Serverless Framework is a node CLI tool which can be installed via npm by running npm install -g serverless . As mentioned the framework can be used against many different cloud providers. AWS, Azure and Google is supported, but also more "exotic" providers like Cloudflare Workers, OpenWhisk and Alibaba Cloud. In this post we will focus on how to use Serverless Framework on AWS.

Serverless Framework concepts

Serverless Framework has four main concepts which you should know before we look on some example code.

Service

You can think of this as an application or as a ... yeah, service. It typically consists of multiple functions (Lambda in our case) and different resources as databases, S3 buckets, API gateway and other managed services.

Functions

On AWS this is equivalent to AWS Lambda. A single piece of code deployed to AWS which triggers based on different kinds of events in the cloud ecosystem. In your service you can define multiple functions, and you can deploy and invoke them via the Serverless Framework CLI.

Events

Events are what trigger your functions you have defined in your service. On AWS this can be anything from a HTTP request from API Gateway, an image uploaded to a S3 bucket, a new entry in a DynamoDB table, a CloudWatch alert and lots more.

Resources

These are any resources which is needed by your service, and typically what your functions use. Typical resources may be a database like DynamoDB , S3 bucket or a SNS topic.

What does this look like in practice?

Below is an example of a service defined in a file called serverless.yml . The service is an API which you can use to create new christmas wishes, and return a list of all your wishes.

service : wishlist provider : name : aws runtime : nodejs12.x region : eu - central - 1 iamRoleStatements : - Effect : "Allow" Action : - dynamodb : Scan - dynamodb : PutItem Resource : "arn:aws:dynamodb:eu-central-1:*:*" functions : wishlist : handler : wishlist.wishlist events : - http : GET wishes newWish : handler : newWish.newWish events : - http : POST wishes resources : Resources : WishlistTable : Type : AWS : : DynamoDB : : Table Properties : TableName : wishlist AttributeDefinitions : - AttributeName : id AttributeType : S - AttributeName : wish AttributeType : S KeySchema : - AttributeName : id KeyType : HASH - AttributeName : wish KeyType : RANGE ProvisionedThroughput : ReadCapacityUnits : 1 WriteCapacityUnits : 1

We start by defining the name for our service, wishlist . Then we define which provider we would like to use, aws , runtime for our functions, nodejs , and which region we would like our service to be deployed to, eu-central-1 . The iamRoleStatements declares that our functions are allowed to query and add items to our DynamoDB table. The last block, resources , defines our DynamoDB table where our wishes are stored.

The functions block could do with a more detailed explanation.

functions : wishlist : handler : wishlist.wishlist events : - http : GET wishes newWish : handler : newWish.newWish events : - http : POST wishes

Here we declare two functions. The wishlist function is a function that returns all wishes from our DynamoDB table. In the events block we define that this should trigger on a http GET request with the path /wishes . The newWish function will, as the name applies, create a new wish in our DynamoDB table. It triggers on a http POST request with the path /wishes . The actual code for the two functions is listed below.

List all wishes

const AWS = require ( 'aws-sdk' ) ; const dynamoDb = new AWS . DynamoDB . DocumentClient ( ) ; module . exports . wishlist = async ( ) => { try { const result = await dynamoDb . scan ( { TableName : 'wishlist' } ) . promise ( ) ; return { statusCode : 200 , body : JSON . stringify ( result ) } } catch ( e ) { return { statusCode : 500 , body : e . message } } }

Add new wish

const AWS = require ( 'aws-sdk' ) ; const dynamoDb = new AWS . DynamoDB . DocumentClient ( ) ; module . exports . newWish = async ( event ) => { try { const result = await dynamoDb . put ( { TableName : 'wishlist' , Item : JSON . parse ( event . body ) } ) . promise ( ) ; return { statusCode : 200 , body : JSON . stringify ( result ) } } catch ( e ) { return { statusCode : 500 , body : e . message } } }

So, how do we actually deploy our service to the cloud?

To deploy our service just run the command sls deploy . Serverless Framework will deploy all your functions and necessary infrastructure, and print the URL for your brand new serverless API at the bottom.

$ sls deploy .. .. .. . Serverless: Stack update finished .. . Service Information service: wishlist stage: dev region: eu-central-1 stack: wishlist-dev resources: 17 api keys: None endpoints: GET - https://ny8fxydfd5.execute-api.eu-central-1.amazonaws.com/dev/wishes POST - https://ny8fxydfd5.execute-api.eu-central-1.amazonaws.com/dev/wishes functions: wishlist: wishlist-dev-wishlist newWish: wishlist-dev-newWish layers: None

So what actually happend here? Under the hood, Serverless Framework creates a CloudFormation template and uploads that to AWS. CloudFormation will take this template and provision all of the necessary services, deploy the functions and link all the services nicely together. In our case the framework created a DynamoDB table, two functions and an API Gateway.

With just a small yaml file, two functions and some shell commands, you suddenly have an API which autoscales automatically and you only pay when the API is in use. I think that's pretty cool!

What's next?

This was only a simple example of what Serverless Framework can do for you when developing serverless applications. In addition to create more complex applications, the framework can be used to test your functions locally or trigger them directly in the cloud, and you can use the framework for accessing logs and other metrics. Serverless Framework also comes with a Dashboard which gives you a "A unified view of your Serverless applications, featuring monitoring, alerting, deployments & much more".