Sefism is free for learners. We are here to help you grow, one step at a time.Join for free
Sefism.
Web

Team Chat App with Threads and Read Receipts on MongoDB

Build a Slack-style team chat for university societies and student project groups, with channels, threaded replies, read receipts, unread counts and live updates. The point is the MongoDB modelling: where to embed and where to reference messages and threads, change streams for real-time delivery, and pagination that stays fast as channels grow.

Difficulty

Intermediate

A small team, or one strong student willing to learn something new.
Effort

1 semester · 2 students

Deliverables

8 to ship

4 optional extras

Suggested stack

MongoDB replica set (Atlas free cluster)Node.js with Socket.IO or WebSocketsMongoDB Node.js driver or MongooseReact or Next.jsk6 for load tests
A suggestion, not a requirement. Swap anything for what you already know.

What you should ship

  • Workspaces, channels and direct messages, with members, roles and invitations
  • Threaded replies with a reply count and latest repliers shown on the parent message
  • Read receipts per member and unread counts per channel, correct across two devices signed in as the same user
  • Live delivery of messages, edits, reactions and receipts through change streams, resuming from a stored resume token after a restart
  • Range-based pagination for channel history and threads, loading older messages on scroll
  • A written modelling document comparing at least two designs for messages, threads and receipts, with the queries each serves
  • Indexes for every main query, justified with explain output
  • A load test with 200 simulated users sending messages, reporting delivery latency and database load

If you have time left

  • Full-text search across a workspace with Atlas Search, respecting channel membership
  • File attachments stored in object storage with metadata in MongoDB
  • Mentions and a notifications inbox built from the same change stream
  • Message retention settings per workspace using TTL, with pinned messages exempt

The problem: group chats without structure

University societies, project groups and small teams mostly organise themselves in messaging groups where every message lands in one flat stream. Replies quote an earlier message instead of forming a thread, decisions scroll away, and nobody can tell who has actually read the announcement about tomorrow's event. Workplace tools solve this with channels, threads and read receipts, but they are built for companies, and their free plans limit history or features.

Building a chat app is a common student project. What makes this one worth a final year is the database design underneath: a chat system is almost entirely a data modelling problem, and the naive design breaks in ways you can measure.

What already exists and the gap

  • Slack and Microsoft Teams have channels, threads and read state, aimed at workplaces.
  • Discord is built around servers and channels for communities, with threads added later.
  • Zulip organises every conversation by topic, a different answer to the same threading problem.
  • Rocket.Chat and Mattermost are open source team chat platforms you can self-host, and Rocket.Chat runs on MongoDB.

The gap for an FYP is not a new chat product. It is a small, well engineered one whose data model you can explain decision by decision, with measurements showing why each choice holds up.

Inspiration

Discord's engineering post "How Discord Stores Billions of Messages" describes starting with all messages in a single MongoDB replica set, indexed on channel and time, and why they later moved to Cassandra as the data outgrew memory. It is a rare public account of chat storage at scale and a good lens for your own design: model for the queries you have, and know where the design stops scaling. Rocket.Chat's open source code is a second reference for how a production chat system uses MongoDB.

What you build

  • Members: join a workspace, post in channels and direct messages, reply in threads, react, edit, and see who has read a message.
  • Workspace admins: create channels, invite and remove members, set roles.
  • Everyone: unread badges per channel, live updates without refreshing, smooth scrolling back through history.

Main flows: post a message, reply in a thread, open a channel on a second device and see unread counts clear, scroll back a thousand messages.

The technically interesting part

  • Embed or reference messages. Embedding messages inside a channel document is the classic unbounded array mistake and runs into the 16 MB document limit. Put messages in their own collection referencing the channel, and show with numbers why.
  • Threads. Store replies as messages with a parentId, and keep a reply count and the last few repliers on the parent, updated with $inc and $push with $slice (the computed and subset patterns). Decide whether a thread reply also appears in the channel.
  • Read receipts without write storms. Recording every reader on every message multiplies writes. Instead keep one membership document per user per channel with a lastReadMessageId, and compute unread counts and "seen by" from it. Compare both designs under load.
  • Live updates with change streams. Watch the messages and memberships collections, filter the stream with a pipeline, fan events out over WebSockets, and store the resume token so a restarted server continues where it left off. Change streams need a replica set, which an Atlas free cluster already is.
  • Pagination. Page history with a compound index on channel and _id and a "before this id" condition, not skip, and prove the difference at 100,000 messages.
  • Indexes. One per main query, each checked with explain output.

Show your supervisor the two modelling designs, the change stream pipeline, and the pagination benchmark.

How to evaluate it

  • Delivery latency: time from send to display on another client, p50 and p95, under the 200-user load test.
  • Pagination: time to load older pages at depth 100, 1,000 and 10,000 messages, range-based versus skip.
  • Write cost: writes per message sent for each read receipt design.
  • Correctness: automated tests for unread counts across two devices, thread counts after deletes, and resume after a server restart.
  • Usability: a real society or project group uses it for a week; collect feedback and fix what they report.

Suggested plan

  • Weeks 1 to 2: list the queries, draft two data models, set up the replica set.
  • Weeks 3 to 5: auth, workspaces, channels, messages, pagination.
  • Weeks 6 to 8: change streams, WebSocket delivery, threads.
  • Weeks 9 to 11: read receipts and unread counts in both designs, load tests.
  • Weeks 12 to 15: a week-long pilot with a real group, fixes, report.

Path to a product

A general chat app will not beat Slack or Discord, but a focused one can find a niche: university societies with event check-ins and announcements, coaching centres, or clinics that need chat tied to their own records. Another route is a chat module other apps embed, a known product category. Either way, a week-long pilot with real users and a measured data model make a strong portfolio piece for backend roles.

Scope warning

Do not build voice or video calls, end-to-end encryption or a mobile app in the core scope. Keep attachments and search as stretch goals. One polished web client is enough.

Learn what you need on Sefism

Get help with this idea

The risk here is building a pretty chat UI on a data model that falls over at the first load test. Tauseef can help you pick the two designs worth comparing, plan the load test, and turn the results into the argument of your report. If you are new here, create a free account first.

Ideas and guidance, not finished projects

These are project ideas and scoping guidance, published free for students to use as a starting point. I do not build, write, or sell final-year projects, and I do not complete coursework for anyone. Take an idea, make it yours, and build it.

Not sure this one fits you?

I help students pick an idea that matches their skills and their deadline, then scope it down until it is finishable. Guidance only, never done for you.

Discuss this idea
Work with me

Stuck on something specific?

Writing only gets you so far. If you want an answer to your situation rather than the general case, book a session and we will work through it together. Sessions are free for approved Sefism members, and a few slots open each week.