Adding real time functionality to your app is an excellent way of keeping your users engaged.

In this post, we are going to see how you can add realtime functionality to our app and the challenges that one encounters while adding realtime functionality.

What is Realtime?

I want patience, and I want it now

This statement kind of summarizes the craving of the 21st-century users to be updated with the latest information.

Realtime is nothing but getting informed about latest events or changes in data as and when they happen.

Remember the time when the whole world communicated via SMS? A few lines of text and an infinite waiting period until your friend finally replied.

No delivery status. No typing indicators πŸ™. Just you, silence and a little excitement.

While this sounds quite romantic, it was very inconvenient πŸ˜….

Soon Whatsapp came with realtime messaging and took the world by storm. After all, the nervousness and excitement when you see your crush typing… It just can’t be described in words 😍!

Sooner or later all major players followed the suite and today we can’t imagine our life without these realtime features.

Realtime features provide an engaging and interactive UXπŸ˜‡

Use Cases of Realtime

Realtime extends way beyond instant messaging to almost every other field or app that we can think of:

  • Live location tracking: Cab booking apps like Uber. Logistics and food delivery apps.
  • Multi-user collaboration: From project management tools like Trello and Jira to Google Docs to multiplayer online games.
  • Live order status: eCommerce apps like Amazon and Flipkart.
  • Live score and commentary: Sports apps like Cricbuzz.
  • Realtime feed: Social media apps like Instagram, Facebook and Twitter.
  • Realtime data analytics: Google Analytics.
  • Live data streaming: Instagram and Facebook Live.
  • Push notifications: Almost every other app to bring users back. For example, blogging platforms.

I am sure you have already started thinking about what features in your app can be realtimeπŸ˜›. Great! Now let’s see how you can add those features to your app!

Adding Realtime Functionalities

Let’s take the example of a realtime messaging app. We just want these three features to be realtime:

  • Messages (push notifications)
  • Online indicator
  • Is typing indicator

Building the frontend interface for the online or is typing indicator is reasonably straight forward if you have some experience building frontend interfaces before. The real challenge though in adding these realtime features to your app is…

Building a realtime backend that is performant, reliable and economical at scale while keeping your sanity.

And that’s what we are going to explore for the rest of this article in detail.

There are two ways of adding realtime data to your app:

Long polling: (Pull based)

The client keeps polling the server for data every few seconds.This is not just a naive way of solving our realtime needs, but it also turns out to be expensive at scale as each additional request to your server costs CPU and memory.

Realtime subscriptions: (Push based)

Server pushes the data to the client in realtime (i.e. on any relevant event or change in data).

This server-side push is the kind of realtime mechanism we want to use for our app as it is very scalable and cost-effective.

Implementing Realtime Subscriptions

The first thing while implementing realtime subscriptions is choosing a communication protocol for it.

Websockets seems to be the most popular protocol when it comes to handling realtime data since its bidirectional (i.e. it can send messages in both directions) and supported by almost all browsers out there.

After all, implementing a basic chat app with WebSockets in NodeJS is as simple as this:

const WebSocket = require('ws');

const webSocketServer = new WebSocket.Server({ port: 8080 });

webSocketServer.on('connection', (webSocket) => {
  webSocket.on('message', (message) => {
    console.log('Received:', message);
    broadcast(message);
  });
});

function broadcast(data) {
  webSocketServer.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
}

The above code simply emits (broadcasts) any messages that it receives to all the connected users in realtime. But you can easily adapt this code to implement one-to-one and group messaging.

While such realtime implementations are good enough on a single server, they don’t work at scale.

Going Distributed

Even simple things become complicated at scale - YourTechBud

I couldn’t agree more on this for realtime functionality.

Let’s imagine the realtime messaging app we just made starts scaling, and we add more servers to balance the load.

Multiple servers

As you would imagine, all our users are not connected to a single server any more. So how does a message travels from one client to the other in realtime if the clients are on two different servers?

This type of realtime backend is what I call distributed realtime backend - The one required at scale and the one that we are interested in😎.

Broadcasting

Broadcasting One easy hack to implement distributed realtime is to broadcast any received messages to all the servers. These servers then notify the message to their connected clients as per the application logic in realtime.

However, at scale, there can be thousands of servers each broadcasting every message to thousands of other servers. If just one server was interested in the message, its simply hogging up all your network and resources.

Thus, broadcasting isn’t performant and hence not a scalable solution at all for our realtime backend. We need something better than this!

Ideally, we want servers to receive only those messages from other servers that they are interested in (i.e. the messages for the clients connected to them.

Let’s say after a lot of research; we figured out a way on how to implement this. So should we call it a day?

No, not yet πŸ˜›.

Filtering Our Results

Even after optimizing the communication between the servers, we still need to write the application layer logic to filter the realtime messages that each client gets.

No one wants his secret messages to be leaked to the public right? We need to make sure that only the right client gets the right data.

Moreover, this filtering logic can be different for each realtime feature in our app.

For example, the group chat demands that a user receives a message if he is a member of that group. On the other hand, the online indicator feature demands the online status of a user be forwarded to a client if that user is in his friends’ list.

Note not just how both this logic are completely different but also that they require you to query the database state in many cases.

This means we need to rewrite the filtering logic every time for each realtime feature in our app. The only way we can get rid of this is by using some kind of a general-purpose rules engine. It would then validate/filter messages before sending them to clients.

Reliability

Remember, when everyone in your peer group knew a secret except you. Even your best friend did not tell it to you. How did you felt at that time? Cheated right? 😒

Now image if a user doesn’t receive a message due to a backend failure. He will feel cheated too! 😒

But wait, why will our beloved server cheat with us in the first place?😦 Trust me it doesn’t want to! It’s just that it isn’t aware of the failures happening in the system.

At scale, failure becomes a norm rather than exception.

Messages getting lost between servers due to network errors is of daily occurrence. Even if you manage to mitigate these errors with retry mechanisms, don’t forget that your servers can crash too.

Imagine what happens if a server dies before broadcasting to any of the other servers just after writing the chat message to a database? Even though we have persisted the data, it wouldn’t be delivered to our clients in realtime.

And these are just a few scenarios that I am listing. If you go on to solve any of these challenges, you would soon realize that new problems keep spawning up!

What If Our Database Itself is Realtime?

Well, that’s an interesting question. It would be great if our database itself can push data in realtime to our clients.

Let’s see if this is a viable solution keeping aside the security aspects of such a solution for now.

If you go on to research, you would be surprised by the fact that even after decades of maturity in database management systems, how hard it is to find a database that can send realtime messages to millions if not billions of clients.

RethinkDB

RethinkDB was the closest we have gotten so far to a general-purpose realtime storage solution, but it seen some difficult times.

Cloud Firestore

Cloud Firestore is another such realtime database which is famous for its ease of use and zero maintenance as its a hosted solution. However, it’s a proprietary technology by Google and becomes costly at scale. And if you were thinking of any aggregations on top of it then seriously, forget it!

CDC Mechanisms

CDC (Change Data Capture) is a set of software design patterns used to determine and track the data that has changed so that you can take action on the changed data.

CDC Architecture

These changes if pumped into a broker or a reliable message queue like Kafka or RabbitMQ, can solve most of our reliability and performance problems.

Though CDC is a very robust way of adding realtime features to your app, there are many downsides to it as well.

The biggest drawback is it adds more moving pieces to our architecture that we need to deploy and maintain. And if you don’t believe me on how painful is maintaining Kafka in production, there’s a company named Confluent whose prime business revolves around helping people do that!

But I Want Realtime Functionality in My App!!

We do! We don’t want the tech giants of the world like Google and Facebook to win our users just because they have a big tech team!😈

I mean we also want to provide the same interactive and engaging realtime experiences to our users at scale.

After all we love our users so much!

So is there an easy way out to implement realtime functionalities? Something that:

  • Provides distributed realtime over any database without impacting the database performance.
  • Offers strong reliability guarantees without introducing heavy components.
  • Scales horizontally.
  • Provides a rules engine so that we don’t need to implement filtering logic for each feature again and again.

It looks like there is one - Space Cloud. Obviously, I didn’t write such a long blog post just to disappoint you at the end by saying there are no hopes! Even I care about your experience a lot πŸ˜›.

Using Space Cloud as a Realtime Engine

Space Cloud is a self-hosted, GraphQL Backend as a Service that provides instant realtime APIs on top of any database.

Yes, you heard that right - on top of any database.

Space Cloud supports all popular databases like Postgres, MongoDB, MySQL, etc. out of the box.

Already in love with Space Cloud? Go ahead and star us on Github!.

Moreover, it provides us with a rules engine (authorization module) that we spoke about earlier.

Thanks to it, the client can securely specify what data it is interested in and receive only that data. No more rewriting realtime functionalities in our app!

Performance and reliability? We got them all! Thanks to the in-built eventing module of Space Cloud.

And guess what? All of these realtime goodies is opensource!

No more vendor lock-ins!

Too excited to see things in action? πŸ˜› Don’t worry; we have already built a sample realtime todo app in ReactJS that uses Space Cloud.

You can also follow this step-by-step guide as well.