Clarification on how the database search works in Mattermost

Summary
The ‘simple’ database search change aimed to prevent stemming for fully quoted strings, but it appears to impact some users even when the input isn’t fully quoted.

Steps to reproduce
Hello everyone, I’m trying to understand how the internal database search works in Mattermost. After upgrading our test server from version 10.5.11 to 10.11.6, the UI “Recent mentions” button starts returning HTTP 499 errors (Client Closed Request) when querying api/v4/posts/search about 30 seconds after a user clicks it in both Web and Desktop clients. The server logs show errors like:

Query error searching posts. caller=“sqlstore/post_store.go:2274” error=“pq: canceling statement due to user request”

Expected behavior
The system should return search results promptly for recent mentions without canceling due to user request, regardless of client (Web, Desktop, Mobile), and should apply the configured text search mechanism consistently across users unless explicitly overridden by input terms or locale.

Observed behavior
For some users, this mechanism behaves as expected and completes quickly, with no error. In the PostgreSQL logs, the problematic query from Web/Desktop clients looks like this:

SELECT , (SELECT COUNT() FROM Posts WHERE Posts.RootId = (CASE WHEN q2.RootId = ‘’ THEN q2.Id ELSE q2.RootId END) AND Posts.DeleteAt = 0) as ReplyCount FROM Posts q2 WHERE q2.DeleteAt = 0 AND q2.Type NOT LIKE ‘system_%’ AND to_tsvector(‘simple’, Message) @@ to_tsquery(‘simple’,‘“@test.user”’) AND ChannelId IN (SELECT Id FROM Channels, ChannelMembers WHERE Id = ChannelId AND ChannelMembers.UserId = ‘{REDACTED}’) ORDER BY q2.CreateAt DESC LIMIT 100

Meanwhile, users who do not experience the issue see a different query, and their searches use a different text search configuration:

SELECT , (SELECT COUNT() FROM Posts WHERE Posts.RootId = (CASE WHEN q2.RootId = ‘’ THEN q2.Id ELSE q2.RootId END) AND Posts.DeleteAt = 0) as ReplyCount FROM Posts q2 WHERE q2.DeleteAt = 0 AND q2.Type NOT LIKE ‘system_%’ AND to_tsvector(‘pg_catalog.english’, Message) @@ to_tsquery(‘pg_catalog.english’,‘“@test.seconduser”’) AND ChannelId IN (SELECT Id FROM Channels, ChannelMembers WHERE Id = ChannelId AND ChannelMembers.UserId = ‘{REDACTED}’) ORDER BY q2.CreateAt DESC LIMIT 100

For all users, the “Recent mentions” view works normally on mobile, and the corresponding PostgreSQL queries use GIN pg_catalog.english. I’ve seen that the change to use the ‘simple’ search was introduced to address “Prevent stemming in DB search when search term is a fully quoted string” (MM-60790; PR #30214).

My questions

  • How does the simple search mode operate in Mattermost, in terms of indexing, tokenization, and stemming behavior?
  • Why can some users’ searches work using the simple configuration while the input is not fully quoted, whereas others fail under the same conditions?

Any explanation of the underlying mechanism and practical guidance to diagnose or reproduce consistently would be appreciated. Thank you.