AWS Lambda and API Gateway: How to Build Your Own API


Table of Contents
Introduction
Overview of AWS Lambda , API Gateway, Amazon DynamoDB
Why Use a Serverless Architecture?
Understanding the Key Components
AWS Lambda: What It Is and How It Works
Amazon API Gateway: Managing API Endpoints
Amazon DynamoDB: NoSQL Database for Serverless Apps
Building the Serverless API
Creating a Lambda Function
Connecting Lambda to API Gateway
Configuring DynamoDB as the Data Store
Conclusion
Introduction
🚀 What is AWS Lambda, API gateway and DynamoDB?
AWS Lambda is a serverless compute service that run your code in response to an event or trigger without needing to manage server.
Amazon API Gateway is a fully managed service that allows developers to create, publish, maintain, and secure APIs at any scale. It acts as an entry point for client requests, routing them to backend services like AWS Lambda, DynamoDB, or other AWS resources.
DynamoDB is a fully managed NoSQL database service provided by Amazon Web Services (AWS). It is designed for high availability, scalability, and low-latency performance, offering a flexible schema and supports key-value and document data models.
🚀 Why use serverless architecture?
Serverless architecture eliminates the need to manage servers, allowing developers to focus on writing code while AWS handles scaling, security, and infrastructure. It is cost-efficient since you only pay for what you use, and it automatically scales based on demand. With faster deployments, built-in fault tolerance, and seamless integration with AWS services like API Gateway and DynamoDB, serverless is ideal for APIs, automation, and event-driven applications. It enhances security with managed patching and IAM controls.
🚀 Setting up of AWS Lambda
search for Lambda in the AWS search panel
Click on Create Function
Fill in the basic information
Lastly, click on create function
🚀 Setting up of API Gateway
From the AWS Console, search for API Gateway in the search bar.
Click on API Gateway under “Services”
Click Create API.
Choose the type of API:
HTTP API – simpler and cheaper, ideal for most use cases.
REST API – full-featured but more complex and expensive.
WebSocket API – for real-time, two-way communication.
Choose HTTP API
Under “Configure routes,” define your route (e.g.,
GET /users
,POST /users
,DELETE /users/{id}
).Click Add Integration:
Choose Lambda function.
Select your Lambda function from the dropdown.
Click Create and attach integration.
Under “Stages,” click Add stage (e.g.,
dev
,test
,prod
).Click Deploy.
You will get a public URL (e.g.,
https://XXXXXXXXXXXXXX/dev
).
🚀 Setting Up DynamoDB from VS Code CLI
🔌 Install AWS Toolkit Extension in VS Code
After installation, click on "IAM Credentials" to start linking your AWS account
🛠 Step-by-Step: Get Your AWS Access Key, Secret Key, and Create a Profile
✅ Step 1: Sign In to Your AWS Account
Go to https://aws.amazon.com/
Click on Sign In to the Console
Use your Root or IAM user credentials (Root is the main account, IAM is for users under it)
✅ Step 2: Navigate to the IAM (Identity and Access Management) Console
In the AWS Management Console, search for IAM in the search bar and click it.
On the left menu, click Users
Click on your username
Go to the Security credentials tab
✅ Step 3: Create Access Key
Scroll to Access keys
Click on Create access key
Choose the use case (e.g., CLI or SDK) and click Next
Click Create access key
You'll get:
Access key ID
Secret access key
Install AWS CLI (if not already installed)
Type
aws --version
to verify the version in command promptIn your vscode terminal type
aws configure --profile myprofile
Use the same Access Key ID, Secret Access key, write any default region (e.g. us-east-1), output format (e.g. json).
❌ Getting an Error?
If you get any error during this process, don’t worry:
Recheck your Access Key and Secret Key
Run
aws configure --profile myprofile
againIf needed, delete the existing key and create a new one from IAM
This is the hard part where we’d need to code things out
Coding Aspect
In this section, we'll walk through how to set up a DynamoDB table and perform basic CRUD operations using the AWS SDK in Node.js. We'll also include logic to check if the table already exists to avoid duplication.
🛠️ Step 1: Set Up DynamoDB Table
import {
DynamoDBClient,
CreateTableCommand,
DescribeTableCommand,
PutItemCommand,
ScanCommand,
DeleteItemCommand,
QueryCommand,
} from "@aws-sdk/client-dynamodb";
// DynamoDB Configuration
const REGION = "your region";
const TABLE_NAME = "your table name";
//added the uuid
const dbClient = new DynamoDBClient({ region: REGION });
🔍 Step 2: Check If Table Exists
const checkTableExists = async () => {
try {
await dbClient.send(new DescribeTableCommand({ TableName: TABLE_NAME }));
return true;
} catch (err) {
if (err.name === "ResourceNotFoundException") {
return false;
}
throw err;
}
;
🧱 Step 3: Create the Table (If Not Exists)
const createTable = async () => {
const tableExists = await checkTableExists();
if (tableExists) {
return { success: true, message: "Table already exists" };
}
const params = {
TableName: TABLE_NAME,
AttributeDefinitions: [
{ AttributeName: "id", AttributeType: "S" },
{ AttributeName: "firstname", AttributeType: "S" }, // GSI Index
],
KeySchema: [{ AttributeName: "id", KeyType: "HASH" }],
GlobalSecondaryIndexes: [
{
IndexName: "FirstNameIndex",
KeySchema: [{ AttributeName: "firstname", KeyType: "HASH" }],
Projection: { ProjectionType: "ALL" },
ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 },
},
],
ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 },
};
try {
await dbClient.send(new CreateTableCommand(params));
return { success: true, message: "Table created successfully" };
} catch (err) {
return {
success: false,
message: "Table creation failed",
error: err.message,
};
}
};
➕ Step 4: Insert Data into Table
const addData = async (data) => {
const requestJSON = JSON.parse(data);
if (
!requestJSON?.username ||
!requestJSON?.firstname ||
!requestJSON?.lastname ||
!requestJSON?.email
) {
return {
success: false,
message: "Missing required fields (id, username, firstname, lastname, email)",
};
}
const params = {
TableName: TABLE_NAME,
Item: {
id: { S: Date.now().toString() },
username: { S: requestJSON.username },
firstname: { S: requestJSON.firstname },
lastname: { S: requestJSON.lastname },
email: { S: requestJSON.email },
},
};
try {
await dbClient.send(new PutItemCommand(params));
return { success: true, message: "Data added successfully" };
} catch (err) {
return { success: false, message: "Failed to add data", error: err };
}
};
📖 Step 5: Read All Data
const fetchallUser = async () => {
const params = {
TableName: TABLE_NAME,
};
try {
const data = await dbClient.send(new ScanCommand(params));
return { success: true, data: data.Items };
} catch (err) {
return { success: false, message: "Failed to fetch data", error: err };
}
};
❌ Step 6: Delete Data By ID
const deleteItem = async (id) => {
if (!id) {
return { success: false, message: "ID is required for deletion" };
}
const params = {
TableName: TABLE_NAME,
Key: {
id: { S: id }, // DynamoDB expects the key in this format
},
};
try {
await dbClient.send(new DeleteItemCommand(params));
return {
success: true,
message: `User with ID ${id} deleted successfully`,
};
} catch (err) {
return { success: false, message: "Failed to delete user", error: err };
}
};
✅ Wrapping Up Create Route so it can be accessed by API Gateway
export const lambdaHandler = async (event, context) => {
console.log("Received event:", JSON.stringify(event, null, 2));
let body;
let statusCode = 200;
const headers = { "Content-Type": "application/json" };
try {
const { routeKey, pathParameters, body: requestBody } = event;
if (routeKey === "GET /users") {
body = await fetchallUser();
} else if (routeKey === "GET /users/{name}") {
body = await getDataByName(pathParameters.name);
} else if (routeKey === "POST /users") {
body = await addData(requestBody);
} else if (routeKey === "DELETE /users/{id}") {
body = await deleteItem(pathParameters.id);
} else if (routeKey === "POST /tables/create") {
body = await createTable();
} else {
throw new Error(`This route does not exist: "${routeKey}"`);
}
} catch (error) {
statusCode = 400;
body = error.message;
}
return {
statusCode,
body: JSON.stringify(body),
headers,
};
};
Now that the heavy lifting is done, go ahead and type sam deploy
in your terminal, this will ship your code straight to AWS Lambda.
Here is a link to the live website: http://apifirstbkt.s3-website-us-east-1.amazonaws.com/
🚀 Conclusion
In this post, we walked through how to interact with DynamoDB using the AWS SDK, covering table creation, checking if a table exists, and performing basic CRUD operations. This kind of setup is a great foundation for building serverless applications with Lambda.
If you're just getting started with AWS or serverless architecture, I encourage you to play around with this setup, try modifying the table schema, or hook it up with a Lambda function and a frontend. There’s so much you can build! 🚀
If you enjoyed this, make sure to give me a like and a follow. Keep building…
Subscribe to my newsletter
Read articles from Adeyanju Tomide directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
