Building a Serverless REST API with Lambda & API Gateway

Building a Serverless REST API with Lambda & API Gateway

Serverless architectures have revolutionized how developers deploy and scale APIs. Building a Serverless REST API with AWS Lambda and API Gateway enables you to create highly available, cost‑effective, and maintenance-free endpoints. This guide provides an end-to-end walkthrough—covering architecture design, IAM setup, Lambda function development, API Gateway configuration, testing, monitoring, and best practices—to help you master serverless API development.


Table Of Contents:

Building a Serverless REST API with Lambda & API Gateway

Overview of Serverless REST APIs

Serverless REST APIs eliminate the need for provisioning or managing servers. AWS Lambda executes your code in response to HTTP requests, while API Gateway routes those requests to the correct function. Benefits include:

  • Automatic Scaling: Lambda scales per request, handling bursts transparently.
  • Pay‑Per‑Use Billing: You’re billed for execution time and request count, reducing idle costs.
  • Reduced Operational Overhead: No servers or patching; focus on business logic.
  • Built‑In Security and Throttling: API Gateway offers authentication, authorization, and rate limiting.

By building a serverless REST API, you leverage these advantages to accelerate development and streamline operations.

» Read More: Top Project Management Tools for Remote Teams


Architecture Diagram and Components

AWS Lambda

Functions written in Node.js, Python, Java, or other languages, executing business logic.

Amazon API Gateway

Publicly exposes REST endpoints, handling routing, validation, and transformations.

Amazon DynamoDB (Optional)

Serverless NoSQL database for persistence.

AWS IAM

Manages permissions for Lambda to invoke other AWS services.

CloudWatch

Logs and metrics for monitoring function execution and API usage.


Prerequisites

Before you begin building a serverless REST API, ensure you have:

  • An AWS Account with administrative privileges.
  • AWS CLI installed and configured (aws configure).
  • Node.js and npm (for Node.js Lambda examples).
  • Serverless Framework or AWS SAM CLI for project scaffolding (optional).

» Read More: Remote Work Best Practices for Distributed Teams


Setting Up IAM Roles and Policies

Proper IAM roles ensure least-privilege access:

Create a Lambda Execution Role
  1. Open the IAM console and choose “Roles” → “Create role.”
  2. Select “Lambda” as the trusted entity.
  3. Attach policies:
    • AWSLambdaBasicExecutionRole (for CloudWatch logs)
    • AmazonDynamoDBFullAccess (if using DynamoDB)
Create an API Gateway Invoke Role

API Gateway uses its own permissions; ensure your API Gateway has permission to execute your Lambda.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "apigateway.amazonaws.com" },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction"
    }
  ]
}

Configure this via AWS CLI or console under “Permissions” in your Lambda function.


Initializing Your Serverless Project

Using Serverless Framework
npm install -g serverless
serverless create --template aws-nodejs --path my-serverless-api
cd my-serverless-api

This generates serverless.yml and handler code.

AWS SAM CLI Alternative
sam init
# Choose AWS Quick Start Templates -> Hello World Example
cd sam-app

These frameworks simplify deployment and infrastructure-as-code.

» Read More: Voice Search Optimization for Hands-Free Queries


Writing Lambda Functions

Setting Up Dependencies

In your project directory, initialize npm and install AWS SDK if needed:

npm init -y
npm install aws-sdk uuid
Implementing CRUD Handlers

Create handler.js with functions for GET, POST, PUT, DELETE:

const AWS = require('aws-sdk');
const { v4: uuidv4 } = require('uuid');
const db = new AWS.DynamoDB.DocumentClient();
const TABLE = process.env.TABLE_NAME;

module.exports.createItem = async (event) => {
  const data = JSON.parse(event.body);
  const id = uuidv4();
  const item = { id, ...data };
  await db.put({ TableName: TABLE, Item: item }).promise();
  return {
    statusCode: 201,
    body: JSON.stringify(item),
  };
};

module.exports.getItem = async (event) => {
  const { id } = event.pathParameters;
  const result = await db.get({ TableName: TABLE, Key: { id } }).promise();
  if (!result.Item) {
    return { statusCode: 404, body: 'Not Found' };
  }
  return { statusCode: 200, body: JSON.stringify(result.Item) };
};

// Similarly implement updateItem and deleteItem

Environment variables (like TABLE_NAME) are defined in your deployment configuration.


Configuring API Gateway Routes

serverless.yml Example
service: my-serverless-api
provider:
  name: aws
  runtime: nodejs14.x
  environment:
    TABLE_NAME: MyDynamoTable

functions:
  createItem:
    handler: handler.createItem
    events:
      - http:
          path: items
          method: post
          cors: true
  getItem:
    handler: handler.getItem
    events:
      - http:
          path: items/{id}
          method: get
          cors: true
  updateItem:
    handler: handler.updateItem
    events:
      - http:
          path: items/{id}
          method: put
          cors: true
  deleteItem:
    handler: handler.deleteItem
    events:
      - http:
          path: items/{id}
          method: delete
          cors: true
resources:
  Resources:
    MyDynamoTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: MyDynamoTable
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST

This file automates API Gateway creation, Lambda wiring, and DynamoDB table setup.

» Read More: Quantum Computing in 2025: Current State & Future Prospects


Deploying Your Serverless API

Deploy with Serverless Framework
serverless deploy
Deploy with AWS SAM
sam build
sam deploy --guided

Deployment outputs include API endpoint URL—used for testing and integration.


Testing Your Serverless Endpoints

Manual Curl Commands
# Create item
curl -X POST https://abc123.execute-api.us-east-1.amazonaws.com/dev/items \
  -H 'Content-Type: application/json' \
  -d '{"name":"Test Item","price":19.99}'

# Get item
curl https://abc123.execute-api.us-east-1.amazonaws.com/dev/items/{id}
Automated Tests

Implement tests using jest and axios:

const axios = require('axios');
test('create and retrieve item', async () => {
  const createRes = await axios.post(API_URL + '/items', { name: 'Item1', price: 9.99 });
  expect(createRes.status).toBe(201);
  const id = createRes.data.id;
  const getRes = await axios.get(API_URL + `/items/${id}`);
  expect(getRes.data.name).toBe('Item1');
});

Continuous integration pipelines can run these on each commit.

» Read More: Kubernetes Cluster Setup on AWS: From Zero to Hero


Enabling CORS and Custom Domain

CORS Configuration

Set cors: true in your function events, or customize in API Gateway console under “CORS Settings.”

Custom Domain Setup
  1. Purchase or manage a domain in Route 53.
  2. In serverless.yml, add:
custom:
  customDomain:
    domainName: api.example.com
    basePath: ''
    stage: ${opt:stage, 'dev'}
    certificateName: '*.example.com'
    createRoute53Record: true
plugins:
  - serverless-domain-manager
  1. Run serverless create_domain and serverless deploy to provision.

Security Best Practices

Input Validation

Sanitize and validate all incoming payloads. Use JSON schema validation via API Gateway Models or Lambda authorizers.

Authentication & Authorization
  • Cognito User Pools: Integrate JWT authentication in API Gateway authorizers.
  • Lambda Authorizers: Custom logic to enforce RBAC and scope checks.
IAM Principle of Least Privilege

Ensure your Lambda execution role only has permissions needed—for example, restricting DynamoDB actions to a specific table.


Logging, Monitoring, and Tracing

CloudWatch Logs

Enable detailed logging in Lambda by using console.log(). View logs in CloudWatch Logs groups per function.

CloudWatch Metrics and Alarms

Monitor metrics: Invocations, Errors, Duration, and Throttles. Create alarms for error rates exceeding thresholds.

AWS X-Ray Tracing

Enable X-Ray in your serverless.yml:

provider:
  tracing:
    lambda: true
    apiGateway: true

This visualizes end-to-end request traces, highlighting bottlenecks.

» Read More: No-Code App Builders Compared: Bubble vs. Adalo vs. Webflow


Error Handling and Retries

Pattern: Try–Catch Blocks

In your Lambda code, wrap external calls in try–catch:

try {
  // business logic
} catch (error) {
  console.error(error);
  return { statusCode: 500, body: 'Internal Server Error' };
}
Dead Letter Queues (DLQ)

Configure Lambda to push failed events to an SQS queue or SNS topic for later inspection and replay:

functions:
  createItem:
    handler: handler.createItem
    deadLetter:
      targetArn: arn:aws:sqs:us-east-1:123456789012:MyDLQ

CI/CD Pipeline for Serverless APIs

GitHub Actions Example
name: Deploy Serverless API
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: us-east-1
      - run: npm install -g serverless
      - run: npm ci
      - run: serverless deploy --stage prod

This automates deployments on each push to main.

» Read More: Pivoting into Data Science: A Roadmap


Optimizing Performance and Cost

Cold Starts Mitigation
  • Keep your function memory at ≥512 MB to reduce initialization latency.
  • Use provisioned concurrency for predictable traffic peaks.
Bundling and Minification

Use tools like webpack or esbuild to reduce package size, improving deployment times and cold start performance.

Cost Management

Monitor Lambda Duration metrics and review high-duration functions. Consider offloading heavy processes to batch jobs or Step Functions to optimize execution costs.


Versioning and Stages

Lambda Versioning

Use versions and aliases to promote code safely:

serverless deploy --stage dev
serverless deploy function -f createItem

Set up aliases: dev, staging, prod to route traffic.

API Gateway Stages

Define dev, staging, and prod stages in API Gateway, each with its own endpoint, throttling, and logging settings.


Testing in Production Safely

Canary Deployments

Use API Gateway Stage Variables and Lambda aliases to shift traffic gradually (10%, 50%, 100%) to new versions—monitor errors before full rollout.

Blue/Green Deployments

Duplicate your infrastructure in parallel stacks, switch DNS records when the new version is validated—ensuring zero-downtime and rollback capability.

» Read More: Conversational Marketing: Building Chatbot Funnels


Advanced Use Cases and Extensions

GraphQL Layer with Apollo Server

Deploy Apollo GraphQL on Lambda, fronted by API Gateway or AppSync, for flexible query patterns and schema evolution.

WebSockets for Real‑Time APIs

Use API Gateway WebSocket support to build chat apps or live dashboards, routing $connect, $disconnect, and $default events to corresponding Lambda functions.

Step Functions for Complex Workflows

Orchestrate multi-step processes—such as file processing or orchestrated approvals—using AWS Step Functions and state machines.


Migration Strategies from Monolithic APIs

Strangler Pattern

Incrementally replace endpoints of your existing monolith by routing new routes through API Gateway and Lambda, while legacy traffic continues to your monolithic service.

Hybrid Architecture

Maintain both serverless and containerized (ECS/EKS) endpoints behind Amazon CloudFront or an Application Load Balancer, transitioning services based on performance and cost considerations.


Common Pitfalls and How to Avoid Them

Overloading Lambda with Business Logic

Keep functions focused on single responsibilities; offload complex logic to specialized services or microservices.

Ignoring Security Headers

Add security headers (CORS, CSP, HSTS) via API Gateway or Lambda responses to protect against web vulnerabilities.

Poor Logging Practices

Log structured JSON instead of free text; enables easier querying and dashboard creation in CloudWatch or Elasticsearch.

» Read More: Rise of Edge Computing: Impacts and Opportunities


Conclusion

Building a Serverless REST API with AWS Lambda and API Gateway empowers teams to deploy scalable, resilient, and cost-efficient services. By following this guide—from setting up IAM roles and writing Lambda functions to configuring API Gateway, implementing security, monitoring, and CI/CD—you’ll establish a robust serverless foundation. Embrace the serverless paradigm to accelerate development, reduce operational burden, and focus on delivering value to your users.

Share This:

Leave a Comment:

Scroll to Top