# AWS IoT Chat Example wires a React client to MQTT over WebSockets

> This AWS sample builds a working chat product on Amazon Cognito, Lambda, DynamoDB, API Gateway and the AWS IoT device gateway, with the browser talking MQTT over WebSockets. It is a teaching codebase with a live demo, deployed through the Serverless Framework, and it is licensed Apache-2.0.

**aws-samples/aws-iot-chat-example** — 💬   Chat application using AWS IoT platform via MQTT over the WebSocket protocol

- Repository: https://github.com/aws-samples/aws-iot-chat-example
- Website: https://d2ab9cgiumpbb1.cloudfront.net
- Stars: 567 · Forks: 128
- Language: JavaScript
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/aws-samples-aws-iot-chat-example

## The browser is an IoT client, not just an HTTP caller

The defining choice in this sample is the transport. Instead of polling a chat API or opening a websocket to a custom server, the browser connects to the AWS IoT device gateway and speaks MQTT over the WebSocket protocol. Messages travel between web clients through AWS IoT, which the project lists first among the services listed in the project, with the stated reason being that MQTT over WebSockets reduces network bandwidth requirements.

Authentication is what makes that possible from a browser. Clients authenticate with Amazon Cognito, and IoT policies are attached so a client can connect to the device gateway, publish to specific topics, and subscribe to and receive messages from specific topics. The service list names Cognito User Pools and Cognito Federated Identities, the latter letting a user sign in through providers such as Facebook and Google.

The rest of the stack is a conventional serverless shape. AWS Lambda provides the compute, API Gateway provides API access control, DynamoDB persists rooms, S3 hosts the static site and CloudFront acts as a proxy and CDN in front of it. The sample calls itself a starting point for building such projects, and its stated purpose is answering common questions such as how to authenticate IoT devices with Cognito.

## Three scripts stand between a clone and a working chat app

The installation path is short but not trivial, and every step matters. The prerequisites are the AWS Command Line Interface, jq for processing command-line JSON, and npm, with Node.js 20 or newer required. Two configuration rules come first: the aws cli region has to be the same as the one you define in api/config.yml, and the cli output format has to be set to json.

Clone the repository, then deploy the backend:

```bash
$ cd api
$ npm install
$ npx serverless@3 deploy --region us-east-1
```

If you use a named AWS profile rather than environment variables, the same command takes an extra argument:

```bash
$ npx serverless@3 deploy --region us-east-1 --profile your-profile-name
```

The stack, including the Lambda functions and CloudFormation resources, is defined in api/serverless.yml, and the API uses esbuild to bundle the Lambda functions so no Babel or Webpack setup is needed. After deployment, two scripts run through a lifecycle hook. The first, api/scripts/attachConfirmUserTrigger.sh, attaches a Lambda function to the PreSignUp trigger on the Cognito User Pool. The second, client/scripts/setup.sh, uses the AWS CLI to query the CloudFormation template output variables and stores them in client/src/config/config.json, which is then imported by client/src/config/index.js. Running that setup script is not optional, since the client needs the AWS IoT endpoint, the API Gateway endpoint and the other configuration variables that the deploy produced.

## The client is React, Vite and Redux Toolkit on ES6

The frontend is a React application written in JavaScript using ES6 syntax, with Vite as the build tool and dev server, and Redux Toolkit for state management. The architecture walkthrough in the documentation splits the client into the frontend and the backend, and the frontend section is where the state management story sits, with a dedicated section on the Redux flows underneath it.

Running the client locally is three commands, and the port matters because the walkthrough points you at a specific address:

```bash
$ cd ../client
$ npm install
$ npm start
```

The documentation then tells you to open http://localhost:5173 and try it out. The same number appears in the Vite setup, which is worth noting if you plan to change it, since the local development URL is hard-coded in the walkthrough rather than left to a config file.

One practical caveat sits at the top of the installation section and is easy to skim past. The project states that it has only been tested on macOS, that Windows users may need to update some of the scripts, and that pull requests to add Windows support are welcome. The shell scripts used in the lifecycle hooks and in the setup step are the likely sticking point, since the deploy path assumes a POSIX shell.

## Rooms, topics and the unread counter problem

The application itself is a small but complete chat product. The feature list covers registering a user, logging in and out, creating a room, joining a room, real-time chat and unread message indicators. The walkthrough follows the same order through the interface.

On the register page at /register and the login page at /login, users are handled by Amazon Cognito User Pools, with the option to federate through Facebook or Google instead. The rooms list at /app/rooms shows the rooms available to join, marks the ones you are subscribed to with an icon, and displays the number of unread messages for those rooms. The page also lets you create a room, and it generates an appropriate topic name to publish on when the room name contains illegal characters, which is the detail that separates a working sample from a broken one.

The chat page itself, shown at a path like /app/room/public/bad-programming-jokes, is where the real-time path shows. You stay subscribed to other rooms, and the unread counters increment as messages arrive for them. Sending a message dispatches it to AWS IoT, and IoT is responsible for fanning it out to every subscriber of that room. All HTTP API endpoints in the app are Lambda functions invoked through API Gateway, so the HTTP traffic handles room listing and creation while the messaging traffic takes the MQTT path.

## A serverless stack you have to take down deliberately

Teardown is a documented command rather than a paragraph of warnings, which is more than many samples manage. The README gives the remove command for the Serverless Framework, run with the same region used for the deploy, and that removes the stack the Serverless Framework deployed, which means the Lambda functions and the CloudFormation resources defined in api/serverless.yml. What it does not obviously cover is everything attached outside that stack. The PreSignUp trigger attached to the Cognito User Pool by api/scripts/attachConfirmUserTrigger.sh, the IoT policies attached to the client identities, and any DynamoDB tables and S3 buckets created along the way are all resources a person created and has to check on.

This is a sample that creates billable AWS infrastructure, which is the main operational difference between it and an ordinary open source project. The services it touches include the IoT device gateway, Lambda, API Gateway, DynamoDB, Cognito, S3 and CloudFront, and each of them has a different pricing shape and a different console. Anyone evaluating the pattern should budget for reading the CloudFormation output before tearing down, rather than assuming the remove command reclaims everything.

## A demo site, Apache-2.0, and a repository that is still moving

The project is published under the Apache-2.0 licence, with a LICENSE file at the top of the repository alongside the README, the api directory, the client directory and the docs directory. That licence matters for a sample more than for a library, because the usual use is to copy a pattern into your own codebase, and Apache-2.0 permits that with attribution and patent terms rather than copyleft obligations.

The documentation also points at a hosted demo at a CloudFront address, with a demo online badge, so you can click through the register, login, rooms and chat screens before deploying anything. A chat GIF in the docs directory shows the real-time behaviour in one frame, and the architecture diagram and the register, login, rooms list and chat screenshots are stored alongside it.

On maintenance, the last push was on 2026-10-18, four days before the current date, and the repository publishes no GitHub releases, so the branch is the only version of the sample. The repository topics name the stack the code expects: amazon-cognito, aws-iot, aws-lambda, dynamodb, mqtt, react, redux, serverless-framework and websockets. A jest badge at the top of the README indicates the project is set up for unit testing, and the documentation has a Testing section in its table of contents.

## Conclusion

Adopt this sample if you are building serverless work on Amazon Cognito and AWS IoT and want a working reference for authentication, topic design and room persistence rather than a product to ship. Do not adopt it as an application framework, since the licence covers the code but the running stack costs AWS money and the project states it has only been tested on macOS. Before deploying, check three things: the region in api/config.yml matches your AWS CLI region and the output format is set to json, the IoT policies attached to the Cognito identity grant only the topics your rooms need, and you know that the teardown command is npx serverless@3 remove --region us-east-1, because a half-removed stack still leaves Cognito and DynamoDB resources behind.

## FAQ

### How do I run the AWS IoT Chat Example locally?

Deploy the backend from the api directory with npx serverless@3 deploy --region us-east-1, then run npm install and npm start in the client directory and open http://localhost:5173. The setup script in client/scripts/setup.sh must run during deployment so the client picks up the generated IoT and API Gateway endpoints.

### What does the AWS IoT Chat Example use MQTT over WebSockets for?

It is how the browser exchanges chat messages. Clients connect to the AWS IoT device gateway, publish to a topic per room, and subscribe to topics, with the stated benefit of reducing network bandwidth requirements compared with heavier transports.

### Which AWS services does the AWS IoT Chat Example use?

AWS IoT for message exchange, Amazon Cognito User Pools and Federated Identities for authentication, AWS Lambda for compute, API Gateway for API access control, DynamoDB for room persistence, S3 for static hosting and CloudFront as a proxy and CDN.

### How do I delete the resources created by the AWS IoT Chat Example?

Run npx serverless@3 remove --region us-east-1 to remove the deployed stack. The documentation does not describe removing the Cognito trigger, the IoT policies or any other resources attached outside the stack, so those need checking separately.

### Does the AWS IoT Chat Example support Windows?

Not as tested. The documentation states the project has only been tested on macOS and that Windows users may need to update some of the scripts, with pull requests to add Windows support welcome.

## Sources

- [aws-samples/aws-iot-chat-example on GitHub](https://github.com/aws-samples/aws-iot-chat-example)
- [Issues](https://github.com/aws-samples/aws-iot-chat-example/issues)
- [License: Apache-2.0](https://github.com/aws-samples/aws-iot-chat-example/blob/master/LICENSE)
- [Project website](https://d2ab9cgiumpbb1.cloudfront.net)
- [README](https://github.com/aws-samples/aws-iot-chat-example/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/aws-samples-aws-iot-chat-example
