How To Implement Live Notifications with Socket.io Elastic Beanstalk and an Amazon Elasticache Redis-Cluster.

Omar
4 min readMar 4, 2019

Problem?

As part of my development of RunwaySupply, a startup idea I have been working on to disrupt the fashion industry, I ran into a ton of user experience related challenges. Many of which I have never implemented before, however the one I am most proud of is live notifications to my end users. RunwaySupply is essentially an applicant tracking system or ATS but specifically targeting the scouting and hiring of models for creative campaigns. As the brand begins to see applicants coming in for the campaigns they have created, I needed to figure out the best way to show them in real time how many applicants they are receiving. I wanted to avoid any scenario where the user had to refresh their dashboard to see if they had new applicants or spamming their inbox with email notifications. Additionally, it was important to keep my solution scalable and cost effective.

Potential Solutions

Why Redis?

Instead of creating my own custom PubSub solution I decided to use Redis because it already provides this functionality. Redis is a fast in memory data store and cache and I learned that I can create a Redis cluster in AWS Elasticache in minutes. I figured that it was better to leverage existing technology then try to reinvent the wheel.

Connecting Redis and Socket.io

https://github.com/socketio/socket.io-redis

By running socket.io with socket.io-redis over it I was able to run multiple socket.io instances in different processes or servers that can all broadcast and emit events to and from each other.

As messages travel over WebSockets I’m able to establish a persistent connection through the Application Load Balancer between each client and WebSocket server.

Elasticache Redis-Cluster Configuration (SERVER-SIDE)

I navigated over to https://console.aws.amazon.com/elasticache. My Elasticache dashboard and chose the Redis option. Then created a cluster which takes a few minutes to process. I then took my configuration endpoint and pass it into the socket.io-redis adapter as an environment variable.

var io = require(“socket.io”)(http); 
//instance of socket io connected to your server
var redis = require(‘socket.io-redis’);
// instance of socket.io-redis
io.adapter(redis({ host: process.env.REDIS_ADDRESS || ‘localhost’, port: 6379 }))
// connecting to redis

Note

localhost:6379 is the default redis address. In elastic beanstalk I added my configuration endpoint as the host and kept the port as the default 6379.

Emitting Events

Its as simple as one line of code.

@EVENT_NAME this is the name of the event you want to emit@DATA this can be any data you want to pass to the client [] {} or “”io.emit(EVENT_NAME, DATA)

Note

If you want to test locally you must install Redis to your computer and run redis-server in the terminal. This will emulate the redis-cluster that AWS provides.

Socket Configuration (CLIENT-SIDE)

I added a Socket listener in my Navigation bar component to check if any events are emitted. I could have also added it in the componentDidMount() lifecycle hook.

@this.setNotification function that will push the notification to an array in state and increment the total notifications on the bell and it will be reflected in real time.socket.on(‘notification’, (data) => {
if(props.user && data.user._id === props.user._id {
this.setNotification(data.notification);
}
})

Now whenever a notification is emitted by a socket on the server this validation I added will route it to the correct Brand. This is because the model’s application belongs to a campaign and that campaign belongs to a brand in that way I am able to tell whether or not to show a notification to a user.

Configuring Elastic Beanstalk and Nginx to Allow WebSockets

By default an Elastic Beanstalk environment uses nginx which does not support WebSockets unless it is manually configured. I could not configure it in the AWS Elastic Beanstalk console and had to use something called .ebextensions because AWS has not built support for it in the console.

I created a folder in the root directory of my back-end application. It must be named .ebextensions and I created a file called 00_enable-websockets.config . The 00 tells Elastic Beanstalk to run this script at the start of deployment.

Inside of 00_enable-websockets.config I added this configuration which configures nginx for Sockets.

container_commands:
enable_websockets:
command: |
sed -i '/\s*proxy_set_header\s*Connection/c \
proxy_set_header Upgrade $http_upgrade;\
proxy_set_header Connection "upgrade";\
proxy_pass_request_headers on;\
' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

When deploying my code I made sure that the .ebextensions get zipped into the final build otherwise it would not work.

LIVE DEMO

As a model verifies their email following a link I have sent to their email after submitting an application, the brand is then instantly notified.

--

--