Zum Inhalt springen

Building a Serverless CRUD API with AWS SAM, Lambda, API Gateway, and DynamoDB

Serverless development has become a go-to strategy for modern application architectures, and with good reason: it allows developers to focus more on building features and less on managing infrastructure. In this article, I walk you through building a fully serverless CRUD API using AWS SAM, Lambda, API Gateway, and DynamoDB all neatly wrapped in Python.

Whether you’re new to AWS SAM or just looking for a practical CRUD example to learn from, this guide has you covered.

Project Overview

The goal of this project was simple: create a clean, scalable, and serverless API capable of Create, Read, Update, and Delete (CRUD) operations on a DynamoDB table. The architecture leverages the following:

  • API Gateway as the HTTP interface
  • AWS Lambda as the compute layer (Python-powered)
  • DynamoDB as the persistent data store
  • AWS SAM (Serverless Application Model) for easy infrastructure deployment

One Lambda function handles all CRUD operations, reducing overhead and keeping the solution neat and maintainable.

1. Project Initialisation

Scaffold a new Python-based SAM project using:

sam init --runtime python3.12 --dependency-manager pip --app-template hello-world --name .

This generates the standard SAM directory structure, giving you a great starting point. Ensure that you initialise the SAM project in a new, empty subdirectory as sam init does not allow initialising a project in a non-empty directory.

2. One Lambda to Rule Them All

Rather than creating separate functions for each CRUD operation, I designed one Lambda function (core/app.py) to handle all actions. It inspects the HTTP path to determine which operation (/create, /read, /update, /delete) to execute.
Why?

  • Less boilerplate
  • Centralized logic
  • Easier maintenance

Here is a code snippet of how I structured the 4 api endpoints in one lambda function

if http_method == 'POST':
        try:
            data = event.get('body', {})
            while isinstance(data, str):
                data = json.loads(data)
            logger.info(f"Request Data (body): {data}")
            match path:
                case '/create':
                    return create(data)
                case '/read':
                    return read(data)
                case '/update':
                    return update(data)
                case '/delete':
                    return delete(data)
                case _:
                    return make_response(404, {'message': 'Path Not Found'})

3. API Gateway Configuration

Inside template.yaml,map the four CRUD routes to the single Lambda function:

Events:
        CreateApi:
          Type: Api
          Properties:
            Path: /create
            Method: post
        ReadApi:
          Type: Api
          Properties:
            Path: /read
            Method: post
        UpdateApi:
          Type: Api
          Properties:
            Path: /update
            Method: post
        DeleteApi:
          Type: Api
          Properties:
            Path: /delete
            Method: post

All these endpoints funnel into the same function, which processes the request and routes it accordingly.

find the rest of the sam template code at: „“

4. DynamoDB Integration

Provision a DynamoDB table named crud, using a simple primary key (id). Through boto3, AWS’s Python SDK, the Lambda function will perform the necessary CRUD operations on the table. As shown in the example below, the function performs a write to the DynamoDB table called ‚crud‘ and returns a response accordingly. This also applies to read, update and delete functions.

def create(data):
    """
    Create a new item in the DynamoDB table.
    """
    try:
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table('crud')
        response = table.put_item(Item=data)
        return make_response(200, {'message': 'Item created successfully'})
    except Exception as e:
        logger.error(f"Error creating item: {e}")
        return make_response(500, {'message': 'Internal Server Error', 'error': str(e)})

5.Application level observability with aws-lambda-powertools & Cloudwatch

Structure logging and tracing using aws-lambda-powertools, this makes debugging easier and ensures operational visibility in CloudWatch. This was a small addition but made a big difference. Simply import and use the tools in your lambda code as shown below.

from aws_lambda_powertools import Logger, Tracer
logger = Logger()
tracer = Tracer()

How they complement cloud monitoring

Tool Monitoring Type Purpose
Logger Application Logging (CloudWatch Logs) Understand what happened and why.
Tracer Distributed Tracing (AWS X-Ray) Understand how requests flow and where bottlenecks occur.

logger in cloudwatch log groups:

6. Deployment with SAM

This is done in 3 steps. validate, build and deploy.

1. sam validate

This command checks your template.yaml (SAM template) for syntax errors and verifies that it’s a valid AWS SAM template.
Think of it like linting for your infrastructure it won’t deploy anything, just confirms your YAML and structure are correct.

2. sam build

This command packages your application code and dependencies, preparing them for deployment.
It:

  • Creates a .aws-sam directory with the build artifacts.
  • Resolves dependencies (like your Python packages from requirements.txt).
  • Zips the code for Lambda functions as needed.

You run this before deploying to ensure everything is packaged correctly.

3. sam deploy –guided

This command deploys your serverless application to AWS.

  • It uploads the artifacts created by sam build to S3.
  • It creates or updates AWS resources defined in your template.yaml (API Gateway, Lambda, DynamoDB, etc.).
  • –guided prompts you interactively for settings like stack name, region, and capabilities.


During your first deploy be keen on the prompts as the answers determine how your project runs.


Then a CloudFormation stack is created and you get prompted to allow the deployment of the stack. AWS SAM uses CloudFormation under the hood to manage resources.


After only a few minutes, your CRUD backend is up and running in AWS.

7. Testing the API

To validate functionality, I created test events mimicking API Gateway POST requests. These can be tested via the Lambda console or SAM CLI.

Here are payloads you can use to test the endpoints through lambda console:

Create (POST /create)

{
  "httpMethod": "POST",
  "path": "/create",
  "body": {
    "id": "123",
    "attribute": "name",
    "value": "John Doe"
  }
}

And the successful lambda response:

Read (POST /read)

Now let’s retrieve what we created in the create test, using a read event test payload

{
  "httpMethod": "POST",
  "path": "/read",
  "body": {
    "id": "123"
  }
}

lambda response:

Read (POST /update)

Now lets update John Doe to Jane Doe using an update event payload.

{
„httpMethod“: „POST“,
„path“: „/update“,
„body“: {
„id“: „123“,
„attribute“: „name“,
„value“: „Jane Doe“
}
}

lambda response:

The name was updated successfully in DynamoDB.

Delete (POST /delete)

Finally, let’s test the delete endpoint using a delete event payload.

{
  "httpMethod": "POST",
  "path": "/delete",
  "body": {
    "id": "123"
  }
}

Our record with ID 123 was successfully deleted from DynamoDB.

Lessons Learned & Pro Tips

SAM is a Productivity Booster
It simplifies the complexity of packaging and deploying serverless applications.

Single Lambda for Multiple Endpoints = Simplicity
Keeping all logic in one handler makes routing clear and concise.

SAM Deployment Prompts Are Repetitive but Important
Sometimes SAM asks the same question twice — answer carefully, especially around authentication and capabilities.

Mind Your Dependencies
Ensure libraries like aws-lambda-powertools are in requirements.txt to avoid runtime issues.
I came across such errors in the lambda response.

To fix this, just add the dependency in the requirements.txt, then sam build and sam deploy, the process should be shorter and faster.

Happy coding!

Follow me for more demos and networking. Kevin Kiruri LinkedIn
Find the source code here: AWS SAM

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert