DEV Community

Cover image for Build and Deploy a Serverless API with AWS SAM, Lambda, Gateway and Docker
Benito Martin for AWS Community Builders

Posted on • Originally published at Medium

2 1

Build and Deploy a Serverless API with AWS SAM, Lambda, Gateway and Docker

In this tutorial, you will create a serverless API that generates a random number between two values using:

  • ✅ AWS Lambda
  • ✅ AWS SAM (Serverless Application Model)
  • ✅ API Gateway
  • ✅ Docker (for local testing)

This tutorial is beginner friendly and only requires basic knowledge of AWS Services.

You can find the whole code repository here

🧱 Project Overview

The app will expose a single POST endpoint:

/generate-random

You send a JSON like:

{ "min": 1, "max": 100 }
Enter fullscreen mode Exit fullscreen mode

And the API will return a random number between min and max:

{ "random_number": 42 }
Enter fullscreen mode Exit fullscreen mode

📦 Prerequisites

To get started, make sure you have:

  • Python installed
  • AWS CLI (configured with credentials)
  • AWS SAM CLI
  • Docker running locally

📁 Project Structure

Here is the directory structure of the project:

├── lambda/
│   ├── lambda_function.py
├── .gitignore
├── .python-version
├── LICENSE
├── README.md
├── pyproject.toml
├── template.yaml
└── uv.lock
Enter fullscreen mode Exit fullscreen mode

🧑‍💻 Setup and Installation

Create the Repository

First, create a new repository (sam-lambda-aws-api) in your GitHub account and clone it locally.

git clone https://github.com/yourusername/sam-lambda-aws-api.git
cd sam-lambda-aws-api
Enter fullscreen mode Exit fullscreen mode

Write the Lambda Function

Create a new folder named lambda in the root of your project. Inside this folder, create the lambda_function.py file. This file will contain the Python code for the Lambda function that handles generating the random number:

import json
import random

def lambda_handler(event, context):
    try:
        body = json.loads(event.get("body", "{}"))
        min_val = int(body.get("min", 1))
        max_val = int(body.get("max", 100))
        random_number = random.randint(min_val, max_val)

        return {
            "statusCode": 200,
            "body": json.dumps({"random_number": random_number})
        }

    except Exception as e:
        return {
            "statusCode": 400,
            "body": json.dumps({"error": str(e)})
        }
Enter fullscreen mode Exit fullscreen mode

Since you are using Python’s built-in json and random modules, there are no additional dependencies for this simple example. For more complex project, you can add external dependencies to a requirements.txt file and save this file in the lambda folder to package the AWS Lambda function with the required dependencies.

Define Your SAM Template

Create the template.yaml file. This is the SAM template that defines the Lambda function, API Gateway, and other AWS resources needed for the app:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  Random Number Generator API

Resources:
  RandomNumberGeneratorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      CodeUri: lambda/
      Events:
        Api:
          Type: Api
          Properties:
            Path: /generate-random
            Method: post
            RestApiId: !Ref ApiGateway

  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: dev
      EndpointConfiguration: REGIONAL
      Cors:
        AllowMethods: "'*'" # Used methods: "'POST,OPTIONS'"
        AllowHeaders: "'Content-Type,Authorization'"
        AllowOrigin: "'*'"

Outputs:
  ApiEndpoint:
    Value: !Sub https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/dev/generate-random
    Description: API Gateway endpoint URL for the Random Number Generator
Enter fullscreen mode Exit fullscreen mode

Here is what the components do:

  • RandomNumberGeneratorFunction: This resource represents your Lambda function. It uses the lambda_function.lambda_handler as the entry point.

  • ApiGateway: The API Gateway is defined to expose the Lambda function as a REST API at the /generate-random path using the POST method.

  • Cors: The CORS configuration allows requests from any origin ('*'), with any method, and with the specified headers. This is useful for development, but in production, you should restrict these to only necessary values.

  • Outputs: This section outputs the URL of the deployed API, which you will use to make requests.

Build and Validate the SAM Application

Now, you need to build the application and validate the template.

Run the following commands:

sam build
sam validate
Enter fullscreen mode Exit fullscreen mode

This will create a .aws-sam directory with the built artifacts, ensuring your project is correctly packaged.

🧪 Local Testing with Docker

You can test the Lambda function locally using Docker (make sure it is running). SAM CLI can emulate AWS Lambda functions on your local machine.

Invoke Lambda Locally

The following command will create a local AWS Lambda Docker image, invoke the function and return the response.

sam local invoke RandomNumberGeneratorFunction
Enter fullscreen mode Exit fullscreen mode

Response:

{
    "random_number": 34
}
Enter fullscreen mode Exit fullscreen mode

Start the API Locally

Alternatively, you can start the API locally and send requests to it. Here also Docker must be running and again a local AWS Lambda image will be created.

sam local start-api
Enter fullscreen mode Exit fullscreen mode

This will spin up a local API Gateway on your machine. The API will be available at http://127.0.0.1:3000.

Now, you can test the API by sending a POST request using curl:

curl -X POST http://127.0.0.1:3000/generate-random \
-H "Content-Type: application/json" \
-d '{"min": 1, "max": 100}'
Enter fullscreen mode Exit fullscreen mode

Response:

{
    "random_number": 5
}
Enter fullscreen mode Exit fullscreen mode

Testing Error Handling

Let's also test how our API handles invalid inputs:

Test with min > max

curl -X POST http://127.0.0.1:3000/generate-random \
-H "Content-Type: application/json" \
-d '{"min": 100, "max": 1}'
Enter fullscreen mode Exit fullscreen mode

Response:

{
    "error": "empty range for randrange() (100, 2, -98)"
}
Enter fullscreen mode Exit fullscreen mode

Test with non-integer values

curl -X POST http://127.0.0.1:3000/generate-random \
-H "Content-Type: application/json" \
-d '{"min": "abc", "max": 100}'
Enter fullscreen mode Exit fullscreen mode

Response:

{
    "error": "invalid literal for int() with base 10: 'abc'"
}
Enter fullscreen mode Exit fullscreen mode

🚀 Deploying to AWS

Once you have tested the app locally, it is time to deploy it to AWS.

Deploy Using SAM

To deploy the app, run the following command:

sam deploy --guided
Enter fullscreen mode Exit fullscreen mode

SAM CLI will prompt you to configure the deployment:

Deployment via sam deploy --guided

SAM will package, deploy, and set up the necessary resources. After the deployment is complete, you will receive an API Gateway URL, which also contains the StageName dev:

Deployed endpoint test

Test the Deployed API

Once deployed, you can test the API by sending a request to the deployed endpoint:

curl -X POST https://hi8mgf8ssl.execute-api.eu-central-1.amazonaws.com/dev/generate-random \
  -H "Content-Type: application/json" \
  -d '{"min": 1, "max": 100}'
Enter fullscreen mode Exit fullscreen mode

Response:

{"random_number": 84}
Enter fullscreen mode Exit fullscreen mode

🧹 Clean Up

To avoid incurring unnecessary costs, remember to delete the resources after you are done:

sam delete
Enter fullscreen mode Exit fullscreen mode

This will remove the stack and all associated resources from AWS.

🎯 Conclusion

In this tutorial, you have successfully built a serverless random number generator API using AWS Lambda, AWS SAM, and API Gateway. This serverless architecture offers several key advantages:

  • Cost-effectiveness: You only pay for the compute time you consume, with no charges when your code is not running.

  • Scalability: The application automatically scales based on demand.

  • Reduced operational overhead: No servers to manage means less time spent on infrastructure maintenance.

  • Fast deployment: The AWS SAM CLI makes it easy to develop, test, and deploy serverless applications.

While this example is simple, it demonstrates the fundamental concepts of serverless architecture that can be applied to more complex applications. The same patterns you used here, defining resources in SAM templates, implementing Lambda functions, and exposing them through API Gateway, can be expanded to build sophisticated serverless applications.

Happy building your serverless applications! 🚀

Top comments (0)