Stop 14 · Build Your Cloud PortfolioProjects · 2/7

Serverless API Project

Part of the Cloud Computing Roadmap

In short

A serverless API costs almost nothing when nobody calls it and scales when your post goes viral. Building one proves you can design with managed pieces instead of servers.

Build a real API entirely on serverless components — API Gateway, functions, and a serverless database — showing you can design and deploy an event-driven, fully managed architecture.

The blob character hands a paper packet through a small shop window beside a brass bell.

Think of it like this

The chemist's night bell

The night chemist doesn't sit at the counter all night. When someone rings the bell, he wakes, hands over the medicine, notes it in his register and goes back to sleep. You only pay him for the times the bell rang.

Watch it happen

POST /notes on a fully managed stack

Client
API Gateway
Lambda
DynamoDB

POST /notes

1/6The client sends JSON. API Gateway checks the route and, if you set it up, the auth token.

The big ideas

What you need to know

Routes, functions, table

Must-haves: CRUD routes in API Gateway, one function per route or a small router, and a DynamoDB table.

Auth and least privilege

Protect write routes with a JWT authorizer, such as Cognito. Give each function access to only what it needs.

Deploy as code

Use AWS SAM, Serverless Framework, CDK or Terraform. Clicking in the console isn't repeatable.

Logs and limits

Show CloudWatch logs, set throttling on the API, and explain cold starts in your README.

See it in code

Walk through the code

ts
1import { DynamoDBClient } from "@aws-sdk/client-dynamodb";2import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";3import { randomUUID } from "node:crypto";4import type { APIGatewayProxyHandlerV2 } from "aws-lambda";5 6const db = DynamoDBDocumentClient.from(new DynamoDBClient({}));7 8export const handler: APIGatewayProxyHandlerV2 = async (event) => {9  const body = JSON.parse(event.body ?? "{}");10  if (!body.title) return { statusCode: 400, body: "title is required" };11  const note = { id: randomUUID(), title: body.title, createdAt: Date.now() };12  await db.send(new PutCommand({ TableName: process.env.TABLE_NAME, Item: note }));13  return { statusCode: 201, body: JSON.stringify(note) };14};

1/4Create the client outside the handler, so warm invocations reuse the connection.

The create-note function on Node.js. The table name comes from an environment variable set by your deploy tool.

Save yourself the pain

Common mistakes

Oops

Giving the function an IAM policy with dynamodb:* on all tables.

Do this instead

Allow only the actions it uses, like PutItem and GetItem, on that one table's ARN.

Oops

Designing DynamoDB tables like SQL tables and scanning for every query.

Do this instead

Plan the access patterns first, then pick keys. Scans read the whole table and get slow and costly.

Your mission

First milestone: one live route

~45 min

Quick check

Why is the DynamoDB client created outside the handler function?

Go deeper

  1. 1Design an API with at least 3-4 distinct endpoints and a clear data model.
  2. 2Wire together API Gateway, a function per endpoint, and a serverless database.
  3. 3Document your cost model — how the pay-per-use pricing works for this specific project.

More projects at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge