Scalable Serverless API: Amazon API Gateway & AWS Lambda

Building a Serverless API with Amazon API Gateway, AWS Lambda, and mastering CRUD operations with DynamoDB: A Step-by-Step Guide

Scalable Serverless API: Amazon API Gateway & AWS Lambda

TL;DR

Learn how to create a powerful serverless API using Amazon API Gateway, AWS Lambda, and DynamoDB. Follow step-by-step instructions to set up the project, create Lambda functions, and deploy the API. Interact with DynamoDB for CRUD operations.

Introduction

In this blog article, we will walk you through the process of building a powerful serverless API using Amazon API Gateway, AWS Lambda, and DynamoDB. This step-by-step guide will help you understand the high-level design, set up the project, and deploy the API, making it clear and easy to follow.

Project Description

Our goal is to create a serverless API that interacts with DynamoDB to perform CRUD operations (Create, Read, Update, Delete) and supports additional operations for testing. The API will be backed by an AWS Lambda function, which will handle incoming requests and interact with the DynamoDB table based on the payload.

Project Skeleton

To achieve our goal, we will have the following components:

  1. Amazon API Gateway: This service will act as the frontend for our API, receiving HTTP requests and routing them to the appropriate Lambda function.

  2. AWS Lambda: We will create a Python 3.7 Lambda function that serves as the backend for our API. It will handle various operations and communicate with the DynamoDB table.

  3. DynamoDB: This NoSQL database service from AWS will store our data. We will create a table and define a primary key for efficient data retrieval.

Tools Used

For this project, we will be using the following AWS services and other tools:

  1. Amazon API Gateway: To create and manage the API endpoints.

  2. AWS Lambda: For serverless computing to process incoming API requests.

  3. AWS DynamoDB: To store and retrieve data in a scalable and reliable manner.

  4. AWS IAM: To allow the Lambda function to carry out the required task.

  5. Postman: To test POST requests on the API and to inspect API responses.

High-Level Design

Our API will have a single resource named "DynamoDBManager," which will handle various methods like POST, enabling different DynamoDB operations. Each API call will be routed to the appropriate Lambda function, allowing us to interact with the DynamoDB table seamlessly.

Setup

Generate Lambda IAM Role

  1. Open the roles page in the IAM console.

  2. Choose Create role.

  3. Create a role with the following properties.

    • Trusted entity: Lambda.

    • Role name: lambda-apigateway-role.

    • Permissions: The custom policy below has the permissions that the function needs to write data to DynamoDB and upload logs.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1428341300017",
      "Action": [
        "dynamodb:DeleteItem",
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:Query",
        "dynamodb:Scan",
        "dynamodb:UpdateItem"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Sid": "",
      "Resource": "*",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow"
    }
  ]
}

Create Lambda Function

  1. Click "Create function" in AWS Lambda Console

  1. Select "Author from scratch". Use name "LambdaFunctionOverHttps" , select "Python 3.7"" as Runtime. Under Permissions, select "Use an existing role", and select "lambda-apigateway-role" that we created, from the drop down. Finally click "Create function" on the bottom right.

  1. Replace the boilerplate coding with the following code snippet and click "Save".
# Sample Python Code for the Lambda Function

from __future__ import print_function

import boto3
import json

print('Loading function')


def lambda_handler(event, context):
    '''Provide an event that contains the following keys:
      - operation: one of the operations in the operations dict below
      - tableName: required for operations that interact with DynamoDB
      - payload: a parameter to pass to the operation being performed
    '''

    operation = event['operation']

    if 'tableName' in event:
        dynamo = boto3.resource('dynamodb').Table(event['tableName'])

    operations = {
        'create': lambda x: dynamo.put_item(**x),
        'read': lambda x: dynamo.get_item(**x),
        'update': lambda x: dynamo.update_item(**x),
        'delete': lambda x: dynamo.delete_item(**x),
        'list': lambda x: dynamo.scan(**x),
        'echo': lambda x: x,
        'ping': lambda x: 'pong'
    }

    if operation in operations:
        return operations[operation](event.get('payload'))
    else:
        raise ValueError('Unrecognized operation "{}"'.format(operation))

Test Lambda Function

Before moving forward, let's test the newly created Lambda function. We'll do a sample echo operation, where the function should output whatever input we pass.

  1. Click the dropdown menu of the "Test" button in the AWS Lambda Console.

  2. Configure a test event with the following JSON payload:

{
    "operation": "echo",
    "payload": {
        "somekey1": "somevalue1",
        "somekey2": "somevalue2"
    }
}

test-lambda-function

With the successful test, we can move on to the next steps!

Create DynamoDB Table

Now, we need to create the DynamoDB table that our Lambda function will utilize.

  1. Open the DynamoDB console.

  2. Click "Create table."

  3. Set the following settings for the table:

    • Table name: lambda-apigateway

    • Primary key: id (string)

  4. Click "Create."

Build API

Our next step is to create the API using Amazon API Gateway.

  1. Go to the API Gateway console.

  2. Click "Create API."

  3. Select "REST API" and give the API a name, such as "DynamoDBOperations."

  4. Click "Create API."

  1. Click "Actions" and then select "Create Resource."

  2. Input "DynamoDBManager" as the Resource Name and click "Create Resource."

  1. Now, let's create a POST method for our API. With the "/dynamodbmanager" resource selected, click "Actions" again and select "Create Method."

  1. Choose "POST" from the dropdown and click the checkmark.

  1. The integration will automatically select "Lambda Function." Choose "LambdaFunctionOverHttps" (our previously created Lambda function) from the list, and click "Save." A popup window will prompt you to add a resource policy to the Lambda function. Click "Ok."

Deploy API

To make our API accessible, we need to deploy it to a stage.

  1. Click "Actions," then select "Deploy API" when post method selected.

  1. For "Deployment stage," select "[New Stage]," and give the stage a name, such as "Prod." Finish it by clicking "Deploy."

  1. Once the deployment is complete, select the "Prod" stage using the stages tab of the sidebar to reveal the "Invoke URL." Copy this URL; it is the endpoint for our API.

Running Our Solution

Now that our API is deployed, let's test it by invoking the Lambda function and interacting with the DynamoDB table.

  1. To create an item in the DynamoDB table, use the following JSON payload in a POST request:
{
    "operation": "create",
    "tableName": "lambda-apigateway",
    "payload": {


        "Item": {
            "id": "1234ABCD",
            "number": 5
        }
    }
}
  1. To execute the API from your local machine, you can use either Postman or cURL:

    • Postman: Select "POST," paste the API invoke URL, and provide the JSON payload in the "Body" section. Click "Send," and the API should return an "HTTPStatusCode" of 200.

  • cURL: Use the following command in your terminal:

      $ curl -X POST -d "{\"operation\":\"create\",\"tableName\":\"lambda-apigateway\",\"payload\":{\"Item\":{\"id\":\"1\",\"name\":\"Bob\"}}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager
    
  1. To verify that the item is inserted into the DynamoDB table, navigate to the DynamoDB console, select the "lambda-apigateway" table, and click the "Explore table items" button.

  1. To retrieve all items from the table, you can use the "list" operation. Send the following JSON payload to the API via Postman:
{
    "operation": "list",
    "tableName": "lambda-apigateway",
    "payload": {
    }
}

You will see the two items that appended lambda-apigateway table as it is below screenshot.

And that's it! You have successfully created a serverless API using Amazon API Gateway, AWS Lambda, and DynamoDB!

Cleanup

Once you have completed the tutorial and want to clean up the resources:

  1. Delete the DynamoDB table "lambda-apigateway" from the DynamoDB console.

  2. Delete the Lambda function "LambdaFunctionOverHttps" from the AWS Lambda console.

  3. Delete the API "DynamoDBOperations" from the Amazon API Gateway console.

  4. Delete the "lambda-apigateway-role" from AWS IAM console.

Conclusion

Building a serverless API with Amazon API Gateway, AWS Lambda, and DynamoDB provides a scalable and cost-efficient solution for your applications. By following this step-by-step guide, you've learned how to create, deploy, and test your serverless API. Now you can leverage this knowledge to build various serverless applications with ease and confidence. Happy coding!

References