RocketChat / RocketChat/Rocket.Chat
channels.getAllUserMentionsByChannel fetches all mentions into memory to compute total count performance regression
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 46.1k
- Forks
- 13.9k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 130
Description
Description
The GET /api/v1/channels.getAllUserMentionsByChannel endpoint calls getUserMentionsByChannel twice per request — once for the paginated result and a second time without skip/limit only to compute the total.
This causes all mention documents in the channel to be loaded into application memory, even though only .length is used. This introduces unnecessary memory allocation, database load, and latency.
File:
apps/meteor/app/api/server/v1/channels.ts (lines 436–449)
// Paginated fetch — correct
const mentions = await getUserMentionsByChannel(this.userId, roomId, {
sort: sort || { ts: 1 },
skip: offset,
limit: count,
});
// Fetches ALL mentions just for .length — problematic
const allMentions = await getUserMentionsByChannel(this.userId, roomId, {});
return API.v1.success({
mentions,
count: mentions.length,
offset,
total: allMentions.length, // only .length is used
});
All other paginated endpoints in this file (such as channels.messages, channels.members, and channels.files) use findPaginated or countDocuments() to compute totals efficiently.
This endpoint appears to be the sole outlier.
Steps to reproduce
- Create a public channel
- Generate a large number of user mentions in the channel (e.g., 5000+)
- Call
GET /api/v1/channels.getAllUserMentionsByChannel?roomId=<id>&count=25&offset=0
- Monitor server memory usage and response time
Expected behavior
The endpoint should obtain the total mention count using a countDocuments() query (or the existing findPaginated pattern), without loading all mention documents into memory.
Response time and memory usage should remain stable regardless of the total number of mentions.
Actual behavior
The endpoint fetches all mention documents from MongoDB into a JavaScript array (allMentions) on every request, then discards everything except .length.
In channels with thousands of mentions this results in:
- O(n) memory allocation per API call
- ~2× database load (two full queries instead of one query + one count)
- Increased response latency proportional to total mentions
Additional context
Affected endpoint:
GET /api/v1/channels.getAllUserMentionsByChannel
Suggested fix:
Replace the second getUserMentionsByChannel call with:
-
a dedicated
countDocuments()query, or -
refactor the endpoint to return
{ data, totalCount }using the samefindPaginatedpattern already used by: -
channels.messages(line 329) -
channels.members -
channels.files
Relevant logs
No error-level logs are produced — this is a silent performance issue.
Diagnosis is based on source inspection:
channels.ts lines 436–449
Impact can be observed via APM/profiling tools monitoring:
- MongoDB query counts
- Node.js heap usage under load
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in apps/meteor/app/api/server/v1/channels.ts at the getAllUserMentionsByChannel handler and compare its total calculation with the channels.messages, channels.members, and channels.files pagination patterns. Verify the endpoint obtains the total without loading every mention document, while preserving the mentions, offset, count, and total response fields. Check the endpoint under a channel with many mentions to confirm memory and latency no longer scale with the full result set.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- mongodb, typescript
- Domain
- api, backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100