This repository is a part of the blog post. Check it out for more information.
This project creates a sample app for demonstrating how to keep anonymous user context when using WebSocket APIs.
The goal is to demonstrate how to handle reconnects without losing user context.
What changed since the original blog post
If you came here from the blog post, the architecture in the diagram (two DynamoDB tables, OnConnect/OnDisconnect/Teleprinter Lambdas, EventBridge-driven OnDelete sweep, cursor-resume on reconnect) is unchanged. The pieces that diverge from the post are mostly about how the user id reaches the backend.
- Identity no longer travels in
Sec-WebSocket-Protocol. The post passes the browser-generated user id through theSec-WebSocket-Protocolheader (new WebSocket(wsUri, userId)). That works, but it lets any client claim any user id (issue #13). The sample now uses a Cognito Identity Pool with unauthenticated identities: the frontend gets short-lived guest IAM credentials, SigV4-signs the$connectURL, and the$connectroute is protected byAuthorizationType: AWS_IAM.OnConnectreads the user id fromrequestContext.identity.cognitoIdentityId, which AWS vouches for. The anonymous reconnecting user experience is the same; the id just isn't forgeable. - IdentityId lives in
localStorage, notsessionStorage. Cognito IdentityIds are stable per browser, so persisting across tabs and reloads is the intended behavior. "Reset Identity" clears it and triggers a freshGetIdon the next connect. - Stage uses
AutoDeploy: true. The post's template uses a staticAWS::ApiGatewayV2::Deploymentsnapshot. With AutoDeploy, route changes (such as flipping$connecttoAWS_IAM) take effect on the live stage automatically. - Lambda runtime bumped to
python3.13. Python 3.9 is past end-of-support and Lambda blocks new function creates on it. - DynamoDB tables use
PAY_PER_REQUEST. The sample is bursty and mostly idle, so on-demand fits better than the provisioned 5/5 in the post. - Frontend dependencies modernized. Migrated to Next.js 16 with the App Router and shipped as a static export.
The post's "Serving authenticated users" note still applies. To accept signed-in users instead of guests, swap the Identity Pool's unauthenticated role for an authenticated one and feed it tokens from a Cognito User Pool (or any other federated identity provider).
This project contains Backend, which you can deploy with AWS SAM template.yml, located in the root of the repository. handlers directory contains all AWS Lambda functions' source code. ws-sessions-frontend directory contains React-based Frontend, which is optional for deployment.
- Create AWS Account in case you do not have it yet or log in to an existing one
- An IAM user or a Role with sufficient permissions to deploy and manage AWS resources
- AWS CLI installed and configured
- Git Installed
- AWS Serverless Application Model (AWS SAM) installed
- Python for changing AWS Lambda functions' code
- NPM for changing the frontend code (React)
The project contains Backend and Frontend. You can deploy Backend only. The deployment of Frontend is optional. Refer to the code in ws-sessions-frontend to understand how it works under the hood, or deploy the React-based Frontend locally or to AWS.
-
Open a terminal and create a new directory, which you will use to clone the repository from GitHub.
-
Clone GitHub repository:
git clone https://github.com/aws-samples/websocket-sessions-management
-
Change directory to the cloned repository:
cd websocket-sessions-management -
Make sure that your terminal can access AWS resources. Use AWS SAM to deploy the backend resources:
sam build && sam deploy --guided -
When prompted:
- Specify a stack name
- Choose AWS Region
- Allow SAM CLI to create IAM roles with the required permissions.
Once you have finished the setup, SAM CLI will save the specified settings in configuration file samconfig.toml so you can use
sam deployfor quicker deployments. -
Note the WebSocketURL value in the output of
sam deploy --guidedcommand. You will need this value for the Frontend later. -
Note the IdentityPoolId value in the same output. The Frontend uses it to obtain anonymous guest IAM credentials and SigV4-sign the WebSocket connect request. The $connect route is configured with
AuthorizationType: AWS_IAM, so the user id (requestContext.identity.cognitoIdentityId) is vouched for by AWS rather than asserted by the client.
To test Frontend on your local machine, you can deploy the React app locally. To do this, follow these steps:
- Make sure you have Node.js 20.9+ and npm installed:
node -v npm -v
- Navigate to
ws-sessions-frontenddirectory:cd ws-sessions-frontend - Install dependencies:
npm install
- Configure the Cognito Identity Pool ID. Create
.env.localinws-sessions-frontend/with theIdentityPoolIdvalue from the SAM outputs:Next.js inlinesNEXT_PUBLIC_IDENTITY_POOL_ID=<region>:<uuid>
NEXT_PUBLIC_*variables at build time, so this works for bothnpm run devand the static export. - Start the development server:
Open http://localhost:3000/ in your browser. The app supports hot reload.
npm run dev
To preview the production static bundle locally:
npm run build # produces ws-sessions-frontend/out/
npx serve out # serves the static bundle on http://localhost:3000Note: This frontend is configured as a Next.js static export (
output: "export"innext.config.mjs), sonpm start(which expects a Node runtime server) does not apply. Deploy the contents ofout/to any static host (S3 + CloudFront, Amplify Hosting, GitHub Pages, etc.).
-
Notice that the app has generated a random user ID for you on startup. The app shows the user ID above in the header. The ID is the Cognito IdentityId for this browser, allocated on first connect from the Identity Pool's unauthenticated identities and cached in
localStorageso it survives reloads. -
Paste the WebSocket URL into the text field. You can find the URL in the console output after you have successfully deployed your SAM template. Alternatively, you can navigate to AWS Management Console (make sure you are in the right region), select the API you have recently deployed, go to
Stages, select the deployed stage and copy theWebSocket URLvalue. -
Press
Connectbutton. The app opens WebSocket connection. -
Press
Tele-readto start receiving the Wikipedia article character by character. New characters will appear in the second half of the screen as they arrive. -
Press
Disconnectbutton to close WebSocket connection. Reconnect again and pressTele-readbutton. Your session resumes from where you stopped. -
Press
Reset Identitybutton. The app closes the WebSocket connection and changes the user ID. PressConnectbutton andTele-readbutton again and your character feed starts from the beginning.

