I really liked how we designed our websocket architecture. After all the infrastructure is written, it’s easy to use and fast to implement new features.
Websockets is used for bidirectional communication. Browsers usually communicate only one direction. The browser requests information from the backend. Without bidirectional communication, to get the latest data, a browser would need to poll (continuously make calls to the backend). With websockets, the backend can send information back to the client without a request.
- User to user communication — another user’s action updates information for a different user.
- Long process — a process takes a long time and we want update a user when the process is finally done.
- Third party action — For example, Stripe confirms payment via webhook on the backend. The backend can then update the user of the successful payment.
- Any communication with an active user.
For serverless applications, this is a challenge, you don’t have a server that is always running to keep track of client connections.
AWS Websocket Gateway. I think of it as a service that maintains client connections. We don’t have to do much. All we need is to write a few lambda functions to keep track of who is currently logged in. (A little bit of hand waving here but plenty of examples on the web on how to do this.)
Integrating Websockets with REST API
You now have the tools, how are you going to use it with your REST API? The best way to show this is via an example flow.
Example of the long running process flow
Step 1 — A user authenticates with an Authentication Server. We’re currently using Firebase but any authentication service that works with AWS Gateway should work.
Step 2 — Register/connect with the Websocket Gateway. Our connect/disconnect lambdas save user mapping information on a database.
Step 3 — User makes the call to start the long running process.
Step 4 — Initial fast process lambda function notifies the long running lambda to start through AWS SNS (more hand waving, but again, plenty of examples on the web on how this is done).
Step 5.1/Step 6 — Immediately return to the user a status.
Step 7 — Run Long Running Process.
Step 8 — Long Running Process is done. Retrieve connection information from the database.
Step 9 — Publish information to client
Step 10 — AWS Websockets sends information back to the browser via websockets.
Step 11 — Browser retrieves data for changed event (see below).
Key Architecture Design that keeps this “Simple”
- We use websocket only in one direction. From the backend to the frontend. The client always communicates via HTTP API to the backend.
- The message we send to the client is just an event key like ‘chat-messages-updated’. There is no other parameters. The client or the React components interested in the ‘event’ will query the backend for updated information. For example, the nav bar component can update its ‘new message count icon’. This involves having a websocket context, that components can “listen” for changes. )Let me know if anybody is interested, I can write another article on this.)
- The method to send a message to a client takes only a user id and an event key.
Backend to frontend communication is really important in order for a user to have a good experience with your application. Serverless might first seem to lack this feature but it is available and can be implemented in a way that works well and is easy to use with an existing REST API.