May 17, 2023
-
10
Min Read

Build on Momento: Instant messaging

Need instant messaging but don’t know where to start? We have you covered.
Allen Helton
Headshot of the blog author
by
Allen Helton
,
,
by
Allen Helton
by
green squirrel logo for momento
Allen Helton
,
,
Caching

The first time I ever used an instant messaging client was back in 2001 with AOL instant messenger. It felt like magic at the time—being able to chat with my school friends about who knows what. Looking back at it now, it was pretty revolutionary and played a big role in shaping the way we interact with software and communicate with each other. Today, instant messaging is an integral part of numerous applications ranging from social media and gaming to customer support and healthcare. However, developing an efficient instant messaging system can be quite challenging.

The first time I built instant messaging, it was way over-engineered. I sent messages over a REST API, saved the message to the database, then fired an event to a messaging service. The messaging service responded to the event by looking at the room id and pushed the message down via a WebSocket to connections that were linked to the room. 

It was closer to “speedy” messaging rather than instant messaging. 

Instant messaging functionality should be simple. It only has two parts: a WebSocket server and a temporary data store. When someone connects to a chat room, pull the entire chat history and send it to the new connection. When someone sends a message, push it to that temporary data store and then send it to all other connections in the room.

Unless you need them for compliance reasons or you built a long-lasting, durable chat application like Slack, chat messages are not something you need to retain. Session-based chats are short-lived and a dime a dozen. When the chat is over, delete all the messages—there’s no need to pay for storage of something that has outlived its benefits, like in-game chat.

Industries

Instant messaging is a staple in a wide range of industries that rely on real-time communication, including:

  1. Customer Support: Improve response times in live chat support systems, providing customers with a seamless experience.
  2. Collaboration Tools: Enhance collaboration within teams by facilitating real-time communication in project management tools and shared workspaces.
  3. Gaming: Enable in-game chats and messaging systems that require low-latency communication between players.
  4. Social Media: Power instant messaging features in social networking platforms, allowing users to chat without delays.
  5. Healthcare: Facilitate secure, real-time communication between healthcare professionals and patients.

Why Momento is the best fit

Using a temporary data store like Momento Cache offers several advantages:

  1. Performance: By storing messages in a cache, Momento Cache reduces response times and ensures that users can access messages almost instantaneously.
  2. Scalability: As a serverless solution, Momento Cache automatically scales to handle fluctuations in traffic, accommodating both small-scale and large-scale applications.
  3. Cost-efficiency: With its pay-as-you-go pricing model, Momento Cache eliminates the need for expensive infrastructure investments and reduces ongoing maintenance costs.
  4. Security: Momento Cache stores messages temporarily, minimizing the risk of unauthorized access to sensitive data.
  5. Flexibility: Momento Cache integrates seamlessly with various messaging protocols and platforms, allowing you to easily adapt it to your specific use case.
  6. Automatic Expiration: All data sent to Momento is configured with a Time to Live (TTL). When the TTL expires, the data is permanently deleted. No need to handle cleanup yourself—we have you covered.

Example app

To see how easily you can build a chat app, check out the example below written with socket.io and the Momento Node.js SDK.


const http = require('http');
const socketIO = require('socket.io');
const dotenv = require('dotenv');
const { CacheClient, Configurations, CredentialProvider } = require('@gomomento/sdk');

dotenv.config();

const server = http.createServer();
const io = socketIO(server, { cors: { origin: '*', methods: ['GET', 'POST'] } });
const cacheClient = new CacheClient({
  configuration: Configurations.Laptop.latest(),
  credentialProvider: CredentialProvider.fromEnvironmentVariable({ environmentVariableName: 'AUTH_TOKEN' }),
  defaultTtlSeconds: 3600 // 1 hour chat history
})

io.on('connection', (socket) => {
  // User joined a chat room
  socket.on('join', async ({ room }) => {
    socket.join(room);

    let chatHistory = [];
    const response = await cacheClient.listFetch('chat', room);
    if (!response.is_miss) {
      chatHistory = response.valueListString().map(m => JSON.parse(m));
    }

    socket.emit('joined', { chatHistory });
  });

  // Message handler
  socket.on('message', async ({ room, message, name }) => {
    const chatMessage = JSON.stringify({ username: name ?? socket.id, message });

    // Broadcast the message to all connected clients in the room, including the person who sent it
    io.to(room).emit('message', { chatMessage });

    await cacheClient.listPushBack('chat', room, chatMessage);
  });

  // Leave a chat room
  socket.on('leave', ({ room }) => {
    socket.leave(room);
  });

  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

server.listen(3000, () => {
  console.log(`Server running on port 3000`);
});

To connect and interact with this websocket on the front-end, we can create a simple html page that uses the socket.io client to communicate with our back-end. Take a look at the script for the client-side of our chat app.


const socket = io('http://localhost:3000');

const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
const messages = document.getElementById('messages');
const userInfo = document.getElementById('user-info');
let name;
let query = window.location.href.split('?');
if(query.length == 2){
  name = query[1].split('=')[1];
}

socket.on('connect', () => {
  console.log('Connected to the server');
  if(!name){
    name = socket.id;
  }
  userInfo.textContent = `You are logged in as ${name}`;
});

socket.on('message', (data) => {
  const message = JSON.parse(data.chatMessage);
  const li = document.createElement('li');

  const usernameStrong = document.createElement('strong');
  usernameStrong.textContent = `${message.username}: `;
  li.appendChild(usernameStrong);

  const messageText = document.createTextNode(message.message);
  li.appendChild(messageText);

  if (message.username == name) {
    li.classList.add('my-message');
  }

  messages.appendChild(li);
});

socket.on('joined', (data) => {
  for (const message of data.chatHistory) {
    const li = document.createElement('li');

    const usernameStrong = document.createElement('strong');
    usernameStrong.textContent = `${message.username}: `;
    li.appendChild(usernameStrong);

    const messageText = document.createTextNode(message.message);
    li.appendChild(messageText);
    
    if (message.username == socket.id) {
      li.classList.add('my-message');
    }
    messages.appendChild(li);
  }
});

For full client side implementation, see the source code.

When a user connects to a chat room, the join socket message will trigger our server-side code to load all messages from a Momento list. We use a list to automatically preserve the order the messages were sent.

When a message is sent, the socket receives an onMessage event that pushes the username and message onto the Momento list and passes it back down to all the other connections in the chat room.

Best practices

When building a chat application with Momento, keep the following best practices in mind:

  • Use a list to store data in the same order it is retrieved
  • Store meta information as a JSON string in the list
  • Set the list TTL slightly longer than the duration of the event. For example, a 30-minute online game should have a TTL of 31 minutes. Customer support chat should live for the max TTL in Momento: 24 hours.

Don’t forget!

Instant messaging is no longer a luxury but a necessity in our fast-paced digital world. Whether you're a social media platform wanting to keep your users engaged, a gaming company seeking to foster real-time communication between players, or a healthcare organization needing to provide quick and secure communication between professionals and patients, Momento Cache is a solution that simplifies and enhances the process.

With Momento, we've brought the complexity of building an instant messaging system down to size, enabling you to focus on what matters most: delivering an exceptional user experience. 

Ready to get started? You can sign up for a free token in the Momento Console and get rolling with our SDK in your favorite programming language!

Happy coding!

Allen Helton
by
Allen Helton
,
,
by
Allen Helton
by
green squirrel logo for momento
by
Allen Helton
,
,
Author
Allen Helton

Allen is an Ecosystem Engineer at Momento. He comes from over a decade of experience working in the public sector tech industry where he played a key role in advancing the adoption of modern technology in the space. Allen drives API-first development and pushes for best-in-class developer experience for customers. When he's not talking about serverless, you can find Allen tending to his homestead. Between feeding the chickens, working in the garden, or building fences, Allen is always outside learning something new and teaching his kids some lessons along the way.

Author
Author
Open