FROMDEV

How to Add Real-Time Chat to a Web App: Build It or Use a Chat API?

A clean UI mockup contrasting database layers with an API integration card.

A chat feature looks small in a ticket: “users can message each other.” In code, it is a distributed system with a UI on top. This guide walks through the parts you must build, with rough effort estimates, so you can decide if you should write them or call a chat API.

The short answer: build when messaging is the product or when you have hard constraints a vendor cannot meet. Use a chat API when chat supports a workflow like buying, booking, or support. The rest of this article shows how to check that against your own case.

The architecture of a chat feature

Every chat feature has the same six layers. Treat them as separate services, even if you ship them in one codebase.

  1. Transport. A live channel between client and server.
  2. Persistence. A store for messages, conversations, and read state.
  3. Fan-out. Code that sends each event to every connected participant.
  4. Presence. Online status and typing indicators.
  5. Notifications. Email and push for users who are away.
  6. Trust and safety. Access rules, moderation, and abuse control.

A prototype covers layers 1 to 3 on one server. A product covers all six.

Transport: WebSockets, SSE, or polling

You have three realistic options for getting a new message to the browser.

For most chat features, WebSockets are the right choice, with SSE or long polling as a fallback for networks that block them. Plan for these details:

Estimate: 2 to 4 engineer-weeks for a gateway you would run in production, including reconnect logic and load tests.

Message persistence and ordering

Storage is where chat bugs hide. Decide these points early.

Schema and keys

A common layout has users, conversations, participants, and messages. Index messages by (conversation_id, created_at, id). Never use the client clock for ordering.

Ordering and idempotency

Two messages can arrive at the server in a different order than users sent them. Pick one source of truth for order: a per-conversation sequence number or a server-assigned time with a tiebreaker ID.

Also make sends idempotent. The client generates a message ID before sending. If the network drops and the client retries, the server sees the same ID and stores one message, not two.

Pagination and gap recovery

Load history with cursor pagination, not offset pagination. Offsets drift when new messages arrive.

When a client reconnects, it should send the last sequence number it saw. The server then replays everything after that number. Without this, users miss messages after a short network drop.

Estimate: 2 to 3 engineer-weeks for the schema, the send path, history, and replay.

Presence, typing indicators, and read state

These features create the most traffic for the least value, so design them with care.

A read pointer that moves on one device must update the others. That is one more event type to fan out.

Estimate: 1 to 2 engineer-weeks.

Push notifications and offline delivery

Most replies arrive when the other person is not looking at your site. Without notifications, conversations stall.

Your notification layer needs to:

Email adds more work: templates, bounce handling, and unsubscribe rules.

Estimate: 2 to 3 engineer-weeks for email plus mobile push.

Moderation and security

Treat chat as a public input surface, even in a private app.

Estimate: 2 to 4 engineer-weeks, and the work does not end at launch.

Scaling

A single WebSocket node handles a lot of idle connections, but a chat system has uneven load. A popular group conversation can create a burst of fan-out to thousands of clients.

Watch these limits as you grow:

The build checklist with effort

Use this as a planning sheet. The numbers are rough estimates from typical projects, not measured data, and your stack will change them.

ComponentEstimate (engineer-weeks)
Transport and reconnect2 to 4
Persistence, ordering, history2 to 3
Presence, typing, read state1 to 2
Notifications (email and push)2 to 3
Moderation and access control2 to 4
Web UI (list, composer, uploads, accessibility)4 to 8
Mobile UI, if you need it4 to 8 per platform
Load testing and monitoring1 to 2

That adds up to roughly 14 to 26 engineer-weeks for web only, before the first maintenance ticket. The UI is often the largest line item, and teams forget it when they say “we only need an API.”

When a chat API wins, and when building wins

A chat API wins when

Building wins when

A short integration sketch

Providers differ, so compare more than one. TalkJS is one option, a chat API. Its SDKs cover JavaScript, React, React Native, Flutter, iOS, and Android, and it has a pre-built, customizable chat UI. Its docs show a pattern that is typical for the category: define a user, open a session, create a conversation, and render the UI.

With the JavaScript SDK, the flow looks like this. Treat it as a sketch and check the current docs for exact calls and for signing sessions on your server.

// 1. Define the current user (from your own auth system)
const me = new Talk.User({ id: "user_123", name: "Ada" });

// 2. Open a session for that user
const session = new Talk.Session({ appId: "YOUR_APP_ID", me });

// 3. Create the inbox and mount it in the page
const inbox = session.createInbox();
inbox.mount(document.getElementById("chat"));

In the React SDK, the same idea uses a Chatbox component that takes an appId, a userId, and a conversationId. You create the conversation from your own event, such as a buyer clicking “Message seller.”

Two design points apply to any provider: your backend stays the source of truth for who may talk to whom, and sessions are authenticated on your server so a user cannot act as someone else.

TalkJS also lists typing indicators and read receipts, moderation tools (flagging, blocking, a profanity filter), notifications, and webhooks. It states ISO 27001 certification, GDPR compliance, and EU hosting with regional options. Its development mode is free, which makes a two-day spike easy to run.

How to run a two-day spike

Before you commit to either route, test the risky parts.

  1. Build a thin vertical slice: two users, one conversation, history, and a reconnect.
  2. Kill the network for ten seconds on one client and check for lost or duplicated messages.
  3. Open three tabs and check unread counts.
  4. Message an offline user and check the notification.
  5. Try to read a conversation you do not belong to.
  6. Ask the vendor for the price at ten times your current user count.

If a vendor fails a step that matters to you, you have a concrete reason to build. If it passes, you saved months.

Decide with your own numbers

Chat is easy to start and hard to finish. Map your needs against the six layers, price the checklist above with your own team’s rates, and run the spike. If the work is not your product’s edge, spend your engineers on what is.

Exit mobile version