4 minutes read

POSTED Oct, 2019 dot IN Serverless

Building A Serverless Backend API Part 2

Serkan Özal

Written by Serkan Özal

Founder and CTO of Thundra

building-serverless-backend-2 X

Before we get started…

  • Check out Part 1 to get set up.

What we’ll go over

  • Updating the Lambda function to handle other types of requests
  • Updating the API Gateway to accept different request methods
  • Creating Reusable Resources
  • Adding Thundra Monitoring to our project

Adding additional Endpoints and Methods

Currently, the only request that we can make is a POST request. To add additional endpoints and request types, just add additional elements to the Events array that was started in Part 1. It will look like this:

 - http:
     path: <Pathway>
     method: <METHOD>
     cors: true
 - http:
     path: <Another-Pathway>
     method: <ANOTHER-METHOD>
     cors: true

Each of these endpoints will trigger the Lambda function they’re nested under, so we need to make sure that our Lambda can handle those request methods.

Updating our Lambda

With the additional endpoints and methods set up, we need to make sure our Lambda function is equipped to handle those events. This tutorial is going to stay limited to GET(all), PUT, DELETE, and GET(by ID) requests, in addition to our already programmed POST request. 

How to structure the Lambda?

There are several different ways to structure our Lambda, but for this tutorial, we’re going to stick to nested if...else statements. In the end it will look something like this:

if (event.path === '/path') {
 if (event.httpMethod === 'GET') {
   //GET logic
 } else if (event.httpMethod === 'POST') {
   //POST Logic

GET (all records)

This method can greatly reduce the performance of your app if you have a lot of records, so use it sparingly.

API Endpoint




We’re using the scan method on the document client here. This will scan every entry for items that match the parameters. In this case, everything will match, this returning every record.


API Endpoint


The {id} portion of the path is how you will grab the ID — keep a note of this for later.


Within the core logic of our Lambda, we first need to determine the value of the ID parameter. This is expressed through


 Keep that in mind for the remaining methods. Pass that variable into a new function:


This one is a little more complex so I’ve added a few more attributes to make it (hopefully) clearer.

  • Key: The primary key of the record in question
  • UpdateExpressions:
"set #<TableHeaderName> = :<PassedVariable>, <...repeat for other variables>"
  • ExpressionAttributeValues: This is where you set the table attribute name. This must match the column header you have in your DynamoDB Table
  • ExpressionAttributeValues: this is the value you are updating to.


API Endpoint



Grab the ID parameter, and pass that variable into a new function:


Again, pretty simple. We just reference the record ID and tell the database to delete it.

GET (by ID)

This version of GET requires a little more work, but not much. We’re going to grab the ID using a path parameter, which will take a slight alteration to our api endpoint.

API Endpoint



Grab the ID parameter, and pass that variable into a new function:


In return we get the record corresponding with the ID we initially referenced.


It’s really kind of amazing how simple it is to create an API using the Serverless Framework. As easy as it is, however, it can still be a pain if you have to do it frequently. One key feature of the Serverless framework is the implementation of Environment Variables. Environment variables are just like any other variable — they are dynamic and can be referenced again and again. What makes them very handy within the Serverless Framework is that they can dynamically create and access resources as needed, making your serverless stack more autonomous. 

To start, we’re going to update a few things:

  • provider.profile: aws-profile ➡️ ${opt:profile, “aws-profile”}
  • provider.region: us-west-2 ➡️ ${opt:region, “us-west-2”}
  • provider.stage: dev ➡️ ${opt:stage, “dev”}

What are we doing here? Instead of hardcoding the values, we are allowing users to specify their values in the form of:

sls deploy --profile client-profile --region us-east-1 --stage prod

If nothing is passed through as an override value, the default values (aws-profile, us-west-2, dev) are used.

Making things dynamic

Now that we have some user-generated values coming into our serverless.yml, let’s update some of our resources to reflect them. First, we’re going to create a ‘custom’ property underneath our ‘provider’ property. Within it, we’re going to create a property called DynamoDBTableName, and assign it a dynamic value.

DynamoDBTableName: ${self:service}-thundra-thunder-${self:provider.stage}

What’s going on here?

  • The variables are marked with the ${} syntax.
  • ‘self:’ references a value that will be found within this serverless.yml file.
  • Anything following ‘self:’ denotes the path to the value that should be referenced, similar to how you would in a nested JSON.

By making changes like this, we can create entirely new resource stacks with the same structures for different stages or regions, all by typing out a few additional commands in the terminal.

Now we just need to update our table name we made previously to reference our newly created dynamic table name. It should look like this:

TableName: ${self:custom.DynamoDBTableName}

Cross-account Reusability

If you quickly scan through your serverless.yml, you’ll notice that your AWS Account ID is still hard-coded. Currently, the Serverless Framework does not have the ability to dynamically fill in an AWS account ID, but the ‘serverless-pseudo-parameters’ plugin grants us that functionality.

To add the plugin, run:

sls plugin install --name serverless-pseudo-parameters

 Then in under provider:iamRoleStatements:Resource, you can convert you account ID to:


With that change made, this serverless.yml can be reused across multiple accounts, and will look something like this:


Adding Thundra Monitoring

Adding Thundra to a project that uses the Serverless Framework is very easy. First, we’re going to install the Thundra plugin by running 

sls plugin install --name serverless-pseudo-parameters

Make sure the plugin is the first listed.

After that, all we need to do is set up an environment variable for our Thundra API Key. Under functions:api:environment, add another environment variable:

thundra_apiKey: <API Key>


This sets up automatic wrapping for our functions and lets us take advantage of Thundra’s Monitoring tools. If you hop into your Thundra Dashboard, you’ll be able to take a deep dive into your app’s metrics.