Engineering

6

mins read

Building Deal Rooms with Real-Time Threads (Without Going Full Chat App)

Taylor's headshot

Taylor Nguyen

Jul 7, 2025

Summary

Hexa’s Deal Rooms let reps and managers collaborate in context — comments, mentions, notes, and updates — all tied to a specific opportunity. But we didn’t want to build a full Slack clone. This article breaks down how we built real-time threaded comments using simple primitives: Redis streams, Postgres triggers, and a thin socket layer that just works.

Summary

Hexa’s Deal Rooms let reps and managers collaborate in context — comments, mentions, notes, and updates — all tied to a specific opportunity. But we didn’t want to build a full Slack clone. This article breaks down how we built real-time threaded comments using simple primitives: Redis streams, Postgres triggers, and a thin socket layer that just works.

The challenge

We wanted reps to be able to:

  • Add notes in real-time during or after calls

  • Mention teammates (@carlos) with notification logic

  • View comment history alongside call summaries and pipeline data

  • Never refresh the page

But we didn’t want to:

  • Maintain presence states

  • Deal with long-lived WebSocket pain

  • Bloat the UI with a full “chat UX”

Core constraint: one thread per deal

Every Deal Room is tied to a single deal ID. That gave us a clean scoping mechanism:

// Client-side socket room join
socket.emit('join', { dealId: 'deal_87234' })

On the backend, we mapped this to a Redis pub/sub channel for lightness and speed:

// Server-side listener
redis.subscribe(`dealroom:${dealId}`)

Real-time without state: the trigger trick

Instead of syncing comment history through a big cache layer, we used PostgreSQL triggers to broadcast events:

CREATE OR REPLACE FUNCTION notify_dealroom_comment()
RETURNS trigger AS $$
BEGIN
  PERFORM pg_notify('dealroom_update', row_to_json(NEW)::text);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

This let us avoid full polling — and meant that the DB was the source of truth, not some middle-layer buffer.

Mentions: just enough parsing

We didn’t need full NLP for @mentions. We used a simple regex + user map:

const mentionedUsers = body.match(/@(\w+)/g)

Then we validate them against the current deal’s team context. If valid, we trigger a notification event with:

  • Author ID

  • Deal ID

  • Mentioned usernames

  • Message text

The result

Deal Rooms feel fast and human — like lightweight sales-focused Slack threads. Reps collaborate without switching tools. Managers see conversation and activity in one place. And we didn’t over-engineer anything.

All of it runs on:

  • 1 Redis instance

  • 1 DB trigger

  • 1 socket server

  • < 500 lines of orchestration logic

Final Thought

Real-time doesn’t have to mean complex. By building for our exact use case — not a generic chat SDK — we created something lighter, clearer, and more durable.

Jump to

Share Article

Share Article

Share Article

Related Reads

More in

Engineering

If it’s not covered here, reach out — or just try Hexa free and see for yourself.

Start Closing Faster

Ready to close faster? Start your free trial today.

Try it free. No contracts, no credit card. Just results, from day one.

  • Used by 2,300+ teams

  • Cancel anytime, no risk

  • 97% user retention after 30 days

Start Closing Faster

Ready to close faster? Start your free trial today.

Try it free. No contracts, no credit card. Just results, from day one.

  • Used by 2,300+ teams

  • Cancel anytime, no risk

  • 97% user retention after 30 days

Start Closing Faster

Ready to close faster? Start your free trial today.

Try it free. No contracts, no credit card. Just results, from day one.

  • Used by 2,300+ teams

  • Cancel anytime, no risk

  • 97% user retention after 30 days