Ravindra BagaleCourses & study guides मराठी Track your progress

Project: Build a WebSocket Chat Room with API Gateway, Lambda and DynamoDB (Source Code)

WhatsApp Web and live support chat need a push channel, not refresh. API Gateway WebSocket keeps a connection; Lambda handles connect, disconnect and message; DynamoDB stores connection IDs.

What you'll learn in this chapter

  • Create WebSocket API routes
  • Track connections in DynamoDB
  • Broadcast with ManageConnections
  • Test with the HTML client and cleanup

1. Everyday example

Why do we need this?

HTTP request/response cannot push a new chat line to everyone already on the page. WebSocket stays open both ways.

What is it?

$connect → save connectionId. $disconnect → delete. Custom route sendmessage → save chat row + post_to_connection to all.

Chat pathBrowserwss://...API GW WebSocketLambda routesDynamoDB connections + messagespost_to_connectionall clients
Need execute-api:ManageConnections on the API.

Download: websocket-chat.zip — connect/disconnect/message + public/index.html

2. Lab

How to do it (step by step)

A. Tables

  1. Table yourname-chat-conn, PK connectionId.
  2. Table yourname-chat-msg, PK messageId.

B. Lambdas

  1. Three functions from the zip (or one router — lab uses three). Env CONNECTIONS_TABLE, MESSAGES_TABLE on message Lambda.
  2. IAM: DynamoDB access + execute-api:ManageConnections for the message role.

C. WebSocket API

  1. API Gateway → Create WebSocket API. Routes: $connect, $disconnect, sendmessage (route selection expression $request.body.action OR integrate sendmessage as default — lab: set route key sendmessage and client sends {"action":"sendmessage","text":"..."} ). Simpler lab path: use route selection $request.body.action and body action sendmessage.
  2. Deploy stage prod. Copy wss:// URL.
  3. Open public/index.html locally, paste wss URL, Connect, Send from two browser tabs.
// client send body example
{"action":"sendmessage","room":"lobby","text":"hello lab"}

Cleanup

  1. Delete WebSocket API (stages first), three Lambdas, both tables, roles.
  2. Closed connections leave stale IDs — deleting the table clears them.

3. Interview

Q. WebSocket vs HTTP polling?

Push is cheaper and faster for chat.

Q. GoneException?

Connection already closed — delete from table.

Q. Why store connectionId?

post_to_connection needs it.

Q. Auth?

Connect route authorizer / JWT query param — next step after lab.

Q. Cleanup?

API + Lambdas + tables.

Try at home

  1. Filter broadcast by roomId.
  2. Add a history GET via HTTP API.

In short

  1. WebSocket API + Lambda + DynamoDB connections.
  2. ManageConnections broadcasts.
  3. Handle GoneException.
  4. Clean up.

Practice Tasks

About this scenario

Vidarbha Cotton Mills is a textiles business in Nagpur. Ganesh Wankhede looks after its IT and cloud work. They count money in INR and run their AWS resources in the ap-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 12

Easy List functions

Why: See which functions exist in this Region.

What to do: List the Lambda functions in ap-south-1.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Invoke a function

Why: Invoke runs the function now and saves its answer in a file.

What to do: Invoke vidarbhacotton-orders-fn and save the response to out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Trust policy for a Lambda role

Why: The trust policy says WHO may take the role.

What to do: Write a trust policy that lets lambda.amazonaws.com assume the role.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Change timeout and memory

Why: More memory also gives more CPU; timeout stops runaway runs.

What to do: Set vidarbhacotton-orders-fn to timeout 30 seconds and memory 512 MB.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Put an item

Why: DynamoDB JSON shows the type of each value: S for string, N for number.

What to do: Put an item into vidarbhacotton-orders with orderId "o-101" (string) and amount 2500 (number).

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Let a function write logs

Why: Without these actions, Lambda logs never appear in CloudWatch.

What to do: Allow logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents on arn:aws:logs:*:*:* only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Hard Let S3 call your function

Why: A resource-based permission is needed before S3 can invoke the function.

What to do: Add permission statement s3invoke to vidarbhacotton-orders-fn so s3.amazonaws.com can call lambda:InvokeFunction from bucket arn:aws:s3:::vidarbhacotton-uploads.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Quick-create an HTTP API for Lambda

Why: Quick create builds an HTTP API, a default route and stage pointing at your function.

What to do: Create an HTTP API named vidarbhacotton-api whose target is arn:aws:lambda:ap-south-1:108737854657:function:vidarbhacotton-orders-fn.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Create a Lambda function

Why: Lambda needs the code zip, a runtime, a handler name and an execution role.

What to do: Create function vidarbhacotton-orders-fn: runtime python3.12, handler app.handler, role arn:aws:iam::108737854657:role/lambda-basic, code in function.zip.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Set environment variables

Why: Keep settings like table names out of the code.

What to do: Set the environment variable TABLE=vidarbhacotton-orders on vidarbhacotton-orders-fn.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Invoke with a JSON payload

Why: In CLI v2, raw JSON needs --cli-binary-format raw-in-base64-out.

What to do: Invoke vidarbhacotton-orders-fn with payload {"orderId":"o-101"} (raw JSON) and save the reply in out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Lambda GB-seconds

Why: Lambda bills memory × time.

What to do: 1,000,000 invocations, 512 MB memory, 200 ms each. How many GB-seconds?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

Revision card: WebSocket chat room. WhatsApp Web and live support need push. Refreshing HTTP every second wastes battery and still feels laggy. API Gateway WebSocket API keeps a connection. Routes $connect, $disconnect, and sendMessage hit Lambda. DynamoDB stores connectionIds and messages. Create WebSocket API, three routes to Lambda, table PK connectionId, tiny HTML client with new WebSocket(wssURL). Two browser tabs connect; one sends hello; both see the message via Management API PostToConnection.
Revision card: WebSocket chat room · Download PNG · Open card page
Revision card: $connect, $disconnect, message. HTTP has one request shape. WebSockets need lifecycle hooks plus your app messages. $connect runs when a client opens the socket — save connectionId. $disconnect removes it. A custom route (e.g. sendMessage) broadcasts. In console: routes $connect, $disconnect, sendMessage → same or separate Lambdas. Deploy stage prod. Copy wss:// invoke URL. On connect, PutItem {connectionId}. On message, Scan/Query connections and post_to_connection each id.
Revision card: $connect, $disconnect, message · Download PNG · Open card page
Revision card: Handle GoneException. Clients leave without a clean $disconnect (closed laptop). Stale connectionIds break broadcasts. PostToConnection on a dead id raises GoneException (410). Delete that connectionId and continue. try/except around post_to_connection; on GoneException delete the DynamoDB row for that connectionId. Broadcast to 5 ids where 1 is stale → 4 get the chat line; stale row is removed automatically.
Revision card: Handle GoneException · Download PNG · Open card page
Comparison: HTTP API vs WebSocket API. HTTP API: One request, one response. WebSocket API: Long-lived push connection.
Comparison: HTTP API vs WebSocket API · Download PNG · Open card page
Interview card: WebSocket vs HTTP polling for chat?. WebSocket keeps a push channel; polling hammers the API and still adds latency. API Gateway WebSocket routes lifecycle and messages to Lambda. wss://…/prod clients; PostToConnection pushes to stored connectionIds.
Interview card: WebSocket vs HTTP polling for chat? · Download PNG · Open card page
Interview card: What is GoneException in WebSocket APIs?. PostToConnection to a closed client returns 410 Gone. Delete that connectionId from DynamoDB and continue broadcasting to others. except ClientError/GoneException: delete_item(Key=connectionId).
Interview card: What is GoneException in WebSocket APIs? · Download PNG · Open card page

More cards: Ravi Sir's Cards.