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
- Navigate to DynamoDB in the AWS Console.
- Click Create table.
- Set Table name to
Items. - Set Partition key to
id(String). - Leave defaults and click Create table.
2. Create the Lambda Function
- Navigate to Lambda → Create function.
- Choose Author from scratch.
- Name:
items-handler, Runtime: Node.js 20.x. - Click Create function.
- 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
- Go to your Lambda function → Configuration → Permissions.
- Click the execution role link to open IAM.
- 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
- Navigate to API Gateway → Create API → HTTP API.
- Click Add integration, choose Lambda, select
items-handler. - Set API name to
items-api. - Add routes:
GET /items→items-handlerPOST /items→items-handlerGET /items/{id}→items-handlerDELETE /items/{id}→items-handler
- 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.