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

Adeyanju TomideAdeyanju Tomide
7 min read

Table of Contents

  1. Introduction

    • Overview of AWS Lambda , API Gateway, Amazon DynamoDB

    • Why Use a Serverless Architecture?

  2. 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

  3. Building the Serverless API

    • Creating a Lambda Function

    • Connecting Lambda to API Gateway

    • Configuring DynamoDB as the Data Store

  4. 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

  1. search for Lambda in the AWS search panel

  2. Click on Create Function

  3. Fill in the basic information

  4. Lastly, click on create function

🚀 Setting up of API Gateway

  1. From the AWS Console, search for API Gateway in the search bar.

  2. Click on API Gateway under “Services”

  3. Click Create API.

  4. 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.

  5. Choose HTTP API

  6. Under “Configure routes,” define your route (e.g., GET /users, POST /users, DELETE /users/{id}).

  7. Click Add Integration:

    • Choose Lambda function.

    • Select your Lambda function from the dropdown.

    • Click Create and attach integration.

  8. Under “Stages,” click Add stage (e.g., dev, test, prod).

  9. Click Deploy.

  10. You will get a public URL (e.g., https://XXXXXXXXXXXXXX/dev).

🚀 Setting Up DynamoDB from VS Code CLI

  1. 🔌 Install AWS Toolkit Extension in VS Code

  2. After installation, click on "IAM Credentials" to start linking your AWS account

  3. 🛠 Step-by-Step: Get Your AWS Access Key, Secret Key, and Create a Profile


    ✅ Step 1: Sign In to Your AWS Account

    1. Go to https://aws.amazon.com/

    2. Click on Sign In to the Console

    3. 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

  1. In the AWS Management Console, search for IAM in the search bar and click it.

  2. On the left menu, click Users

  3. Click on your username

  4. Go to the Security credentials tab


✅ Step 3: Create Access Key

  1. Scroll to Access keys

  2. Click on Create access key

  3. Choose the use case (e.g., CLI or SDK) and click Next

  4. Click Create access key

  5. You'll get:

    • Access key ID

    • Secret access key

  1. Install AWS CLI (if not already installed)

  2. Type aws --version to verify the version in command prompt

  3. In your vscode terminal type aws configure --profile myprofile

  4. 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 again

  • If 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…

0
Subscribe to my newsletter

Read articles from Adeyanju Tomide directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Adeyanju Tomide
Adeyanju Tomide