Chapter 1 · Lesson 3

Understanding AWS Serverless Services

Meet the three core services that power every serverless application on AWS — Lambda, API Gateway, and DynamoDB — and see exactly how they work together to handle a real request.

AWS Lambda — Run Code on Demand

AWS Lambda is a compute service that runs your code in response to events — an HTTP request, a file uploaded to S3, a message on a queue, a scheduled timer. You upload your function, configure how much memory it gets, and Lambda handles everything else: provisioning servers, patching the operating system, scaling up under load, and scaling back down to zero when traffic stops.

The core idea is simple: you pay only for the milliseconds your code actually runs, and you never touch a server. A function that handles 10,000 requests per day and a function that handles 10,000,000 look identical from your perspective — Lambda scales the underlying infrastructure automatically.

  • Runtime: Node.js 20 (and many others — Python, Java, Go, .NET).
  • Execution limit: Up to 15 minutes per invocation.
  • Memory: 128 MB – 10,240 MB (CPU scales proportionally).
  • Free Tier: 1 million requests and 400,000 GB-seconds of compute per month, every month.

A minimal Lambda function looks like this:

handler.mjs — ES module style (recommended)

export const handler = async (event) => {
  console.log("Event received:", JSON.stringify(event, null, 2));

  return {
    statusCode: 200,
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message: "Hello from Lambda!" }),
  };
};
Always init SDK clients outside the handler
Lambda reuses the execution environment between warm invocations. Initializing AWS SDK clients (like DynamoDBDocumentClient) at module scope means they are created once and reused, not re-created on every request — cutting latency and cost.

API Gateway — The Managed Front Door

API Gateway is a fully managed service that accepts HTTP requests from the internet and routes them to a backend — in our case, a Lambda function. It handles the heavy lifting that would otherwise fall on you: TLS termination, throttling, authentication hooks, CORS headers, request validation, and automatic scaling.

AWS offers two flavours relevant to Lambda:

Type Best for Notable features
HTTP API Most REST-style backends Cheaper, lower latency, JWT authorizers, CORS built-in
REST API Complex APIs needing full control Request/response transforms, API keys, usage plans, caching

In this course we use HTTP API — it is the recommended default for new Lambda-backed APIs. It is faster to configure, less expensive, and covers everything beginners need.

When API Gateway forwards a request to Lambda it wraps it in a proxy event object. Your handler reads event.httpMethod, event.path, event.queryStringParameters, and event.body (a JSON string you must parse). Your return value must be an API Gateway proxy response — a plain JavaScript object with statusCode, optional headers, and a body string.

Always stringify the body
API Gateway expects body to be a string, not an object. Wrap it with JSON.stringify() every time, even for error responses.

DynamoDB — Serverless NoSQL Database

DynamoDB is AWS's fully managed, key-value and document database. Like Lambda, it has no servers to patch, no capacity to pre-provision (in on-demand mode), and it scales from zero to millions of requests per second automatically. This makes it the natural database companion for Lambda.

Data is organized into tables. Every item (row) must have a partition key and optionally a sort key. Items in the same table can have different attributes — there is no fixed schema beyond the keys.

  • On-demand capacity mode: Pay per request. No planning needed. Perfect for variable or unpredictable traffic.
  • Provisioned capacity mode: Reserve read/write units in advance. More predictable cost at steady high throughput.
  • Free Tier: 25 GB storage, 25 WCU, 25 RCU per month — permanently free.

We interact with DynamoDB from Lambda using the AWS SDK v3. The DynamoDBDocumentClient wrapper from @aws-sdk/lib-dynamodb handles marshalling JavaScript types to DynamoDB's wire format automatically:

db.mjs — client initialised at module scope

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand, PutCommand } from "@aws-sdk/lib-dynamodb";

const raw = new DynamoDBClient({ region: "us-east-1" });
export const db = DynamoDBDocumentClient.from(raw);

// Example: fetch one item by partition key
export const getItem = async (id) => {
  const { Item } = await db.send(
    new GetCommand({
      TableName: process.env.TABLE_NAME,
      Key: { id },
    })
  );
  return Item ?? null;
};

How They Work Together

Each service has a single, focused job. Together they form a complete, fully managed backend that needs no servers:

  1. A client (browser, mobile app, curl) sends an HTTP request.
  2. API Gateway receives it, validates it, and invokes your Lambda function.
  3. Lambda runs your business logic and queries DynamoDB.
  4. DynamoDB returns the data.
  5. Lambda builds the response and returns it to API Gateway.
  6. API Gateway forwards the HTTP response back to the client.
Client Browser / Mobile App API Gateway HTTP API TLS · Auth · Throttle CORS · Routing Lambda Node.js 20 Business Logic SDK v3 Calls DynamoDB NoSQL Table On-Demand Auto-Scaling request response invoke proxy res query data AWS Managed Infrastructure — no servers to operate
Full serverless request lifecycle. The dashed blue line shows the inbound request path; the teal line shows the response. Everything inside the dashed rectangle is fully managed by AWS.

Service Roles at a Glance

Here is a quick reference mapping each service to its responsibility in the stack:

Service Category Your job AWS's job
API Gateway Networking Define routes, choose auth method TLS, scaling, throttling, CORS, invoke Lambda
Lambda Compute Write handler code, set memory/timeout Servers, OS patches, scaling, cold-start pooling
DynamoDB Storage Design table keys, write queries Replication, backups, partitioning, scaling
IAM Security Attach least-privilege policy to Lambda role Policy enforcement, credential rotation
CloudWatch Observability Add console.log statements Log storage, metrics dashboards, alarms
IAM and CloudWatch are always in the picture
Even though the diagram above focuses on the three main services, every Lambda function needs an IAM execution role that grants permission to write logs to CloudWatch and call DynamoDB. AWS SAM creates a sensible default role for you — we will examine it in a later lab.

What This Looks Like in SAM

AWS SAM (Serverless Application Model) is the Infrastructure-as-Code tool we use throughout this course. A complete serverless backend — API Gateway, Lambda, and DynamoDB — is described in a single template.yaml file. Here is the skeleton so the big picture is clear before we dive into each service:

template.yaml — SAM skeleton

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs20.x
    Environment:
      Variables:
        TABLE_NAME: !Ref ItemsTable

Resources:
  # 1. The HTTP API — SAM creates it automatically when you add an Api event
  ItemsFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handler.handler
      Events:
        GetItems:
          Type: HttpApi
          Properties:
            Path: /items
            Method: GET
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref ItemsTable

  # 2. The DynamoDB table
  ItemsTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String

That is the entire infrastructure definition. SAM expands this into the full CloudFormation stack, creates the API Gateway HTTP API, wires the Lambda trigger, and grants the function permission to read and write the table.

Lesson Summary
  • Lambda runs your code on demand with zero server management. You pay per millisecond of execution, and it scales automatically from zero to millions of requests.
  • API Gateway (HTTP API) is the secure, scalable front door. It handles TLS, throttling, CORS, and routing before handing the request off to Lambda as a proxy event.
  • DynamoDB is the natural serverless database — fully managed, on-demand scaling, and billed per request rather than per provisioned server.
  • The request lifecycle is: Client → API Gateway → Lambda → DynamoDB → Lambda → API Gateway → Client. Each hop is managed by AWS; you write only the Lambda handler code.
  • IAM roles and CloudWatch Logs are always part of the picture even when not shown explicitly — SAM configures sensible defaults for both.