Skip to content
← AWS Learning Projects
Intermediate 3 min read

Build a Serverless REST API with API Gateway and Lambda

Create a fully serverless REST API using AWS API Gateway and Lambda functions, backed by a DynamoDB table.

Overview

This project guides you through building a serverless REST API on AWS. You will create Lambda functions that handle CRUD operations, expose them via API Gateway, and persist data in DynamoDB — all without managing any servers.

What You Will Learn

  • Creating Lambda functions with Node.js (or Python)
  • Configuring API Gateway HTTP API
  • Connecting Lambda to DynamoDB
  • Using IAM roles to grant least-privilege permissions
  • Testing API endpoints with curl or Postman

Prerequisites

  • An AWS account
  • Basic knowledge of JavaScript or Python
  • Familiarity with REST concepts (GET, POST, PUT, DELETE)

Architecture

Client → API Gateway (HTTP API) → Lambda Function → DynamoDB Table

Steps

1. Create the DynamoDB Table

  1. Navigate to DynamoDB in the AWS Console.
  2. Click Create table.
  3. Set Table name to Items.
  4. Set Partition key to id (String).
  5. Leave defaults and click Create table.

2. Create the Lambda Function

  1. Navigate to LambdaCreate function.
  2. Choose Author from scratch.
  3. Name: items-handler, Runtime: Node.js 20.x.
  4. Click Create function.
  5. Replace the default code with:
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  GetCommand,
  PutCommand,
  DeleteCommand,
  ScanCommand,
} from "@aws-sdk/lib-dynamodb";
import { randomUUID } from "crypto";

const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const TABLE = "Items";

export const handler = async event => {
  const method = event.requestContext.http.method;
  const id = event.pathParameters?.id;

  if (method === "GET" && !id) {
    const { Items } = await client.send(new ScanCommand({ TableName: TABLE }));
    return { statusCode: 200, body: JSON.stringify(Items) };
  }

  if (method === "GET" && id) {
    const { Item } = await client.send(
      new GetCommand({ TableName: TABLE, Key: { id } })
    );
    return Item
      ? { statusCode: 200, body: JSON.stringify(Item) }
      : { statusCode: 404, body: "Not found" };
  }

  if (method === "POST") {
    const body = JSON.parse(event.body);
    const item = { id: randomUUID(), ...body };
    await client.send(new PutCommand({ TableName: TABLE, Item: item }));
    return { statusCode: 201, body: JSON.stringify(item) };
  }

  if (method === "DELETE" && id) {
    await client.send(new DeleteCommand({ TableName: TABLE, Key: { id } }));
    return { statusCode: 204, body: "" };
  }

  return { statusCode: 405, body: "Method not allowed" };
};

3. Attach an IAM Policy to Lambda

  1. Go to your Lambda function → ConfigurationPermissions.
  2. Click the execution role link to open IAM.
  3. Attach an inline policy granting DynamoDB access:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:DeleteItem",
        "dynamodb:Scan"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/Items"
    }
  ]
}

4. Create the API Gateway

  1. Navigate to API GatewayCreate APIHTTP API.
  2. Click Add integration, choose Lambda, select items-handler.
  3. Set API name to items-api.
  4. Add routes:
    • GET /itemsitems-handler
    • POST /itemsitems-handler
    • GET /items/{id}items-handler
    • DELETE /items/{id}items-handler
  5. Click Next through stages, then Create.

5. Test the API

Copy the Invoke URL from the API Gateway console and test:

BASE="https://your-api-id.execute-api.us-east-1.amazonaws.com"

# Create an item
curl -X POST "$BASE/items" \
  -H "Content-Type: application/json" \
  -d '{"name": "Widget", "price": 9.99}'

# List all items
curl "$BASE/items"

# Get a specific item
curl "$BASE/items/ITEM_ID"

# Delete an item
curl -X DELETE "$BASE/items/ITEM_ID"

Clean Up

Delete the API Gateway, Lambda function, and DynamoDB table to avoid charges.

Going Further

  • Add request validation with API Gateway models.
  • Secure the API with Cognito or an API key.
  • Deploy infrastructure as code using AWS SAM or CDK.