diff --git a/lib/types/message-types-enum.js b/lib/types/message-types-enum.js
--- a/lib/types/message-types-enum.js
+++ b/lib/types/message-types-enum.js
@@ -2,6 +2,8 @@
 
 import invariant from 'invariant';
 
+// Should be in sync with native/cpp/CommonCpp/NativeModules/\
+// PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h
 export const messageTypes = Object.freeze({
   TEXT: 0,
   // Appears in the newly created thread
diff --git a/lib/types/thread-types-enum.js b/lib/types/thread-types-enum.js
--- a/lib/types/thread-types-enum.js
+++ b/lib/types/thread-types-enum.js
@@ -6,6 +6,8 @@
 import { values } from '../utils/objects.js';
 import { tNumEnum } from '../utils/validation-utils.js';
 
+// Should be in sync with native/cpp/CommonCpp/NativeModules/\
+// PersistentStorageUtilities/ThreadOperationsUtilities/ThreadTypeEnum.h
 export const thinThreadTypes = Object.freeze({
   //OPEN: 0,   (DEPRECATED)
   //CLOSED: 1, (DEPRECATED)
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
@@ -47,6 +47,7 @@
   std::optional<int> getSyncedDatabaseVersion(sqlite3 *db) const;
   std::vector<MessageEntity>
   processMessagesResults(SQLiteStatementWrapper &preparedSQL) const;
+  std::string getThickThreadTypesList() const;
 
 public:
   static std::string sqliteFilePath;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -2,6 +2,7 @@
 #include "Logger.h"
 
 #include "../NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h"
+#include "../NativeModules/PersistentStorageUtilities/ThreadOperationsUtilities/ThreadTypeEnum.h"
 #include "entities/CommunityInfo.h"
 #include "entities/EntityQueryHelpers.h"
 #include "entities/EntryInfo.h"
@@ -1491,13 +1492,42 @@
   removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllMessagesSQL);
 }
 
+std::string SQLiteQueryExecutor::getThickThreadTypesList() const {
+  std::stringstream resultStream;
+  for (auto it = THICK_THREAD_TYPES.begin(); it != THICK_THREAD_TYPES.end();
+       ++it) {
+    int typeInt = static_cast<int>(*it);
+    resultStream << typeInt;
+
+    if (it + 1 != THICK_THREAD_TYPES.end()) {
+      resultStream << ",";
+    }
+  }
+  return resultStream.str();
+}
+
 std::vector<MessageEntity> SQLiteQueryExecutor::getInitialMessages() const {
   static std::string getInitialMessagesSQL =
-      "SELECT * "
-      "FROM messages "
-      "LEFT JOIN media "
-      "  ON messages.id = media.container "
-      "ORDER BY messages.id;";
+      "SELECT "
+      "  s.id, s.local_id, s.thread, s.user, s.type, s.future_type, "
+      "  s.content, s.time, m.id, m.container, m.thread, m.uri, m.type, "
+      "  m.extras "
+      "FROM ( "
+      "  SELECT "
+      "    m.*, "
+      "    ROW_NUMBER() OVER ( "
+      "      PARTITION BY thread ORDER BY m.time DESC, m.id DESC "
+      "    ) AS r "
+      "  FROM messages AS m "
+      ") AS s "
+      "LEFT JOIN media AS m "
+      "  ON s.id = m.container "
+      "INNER JOIN threads AS t "
+      "  ON s.thread = t.id "
+      "WHERE s.r <= 20 OR t.type NOT IN ( " +
+      this->getThickThreadTypesList() +
+      ") "
+      "ORDER BY s.time, s.id;";
   SQLiteStatementWrapper preparedSQL(
       SQLiteQueryExecutor::getConnection(),
       getInitialMessagesSQL,
@@ -1514,12 +1544,12 @@
        stepResult = sqlite3_step(preparedSQL)) {
     Message message = Message::fromSQLResult(preparedSQL, 0);
     if (message.id == prevMsgIdx) {
-      messages.back().second.push_back(Media::fromSQLResult(preparedSQL, 9));
+      messages.back().second.push_back(Media::fromSQLResult(preparedSQL, 8));
     } else {
       prevMsgIdx = message.id;
       std::vector<Media> mediaForMsg;
-      if (sqlite3_column_type(preparedSQL, 9) != SQLITE_NULL) {
-        mediaForMsg.push_back(Media::fromSQLResult(preparedSQL, 9));
+      if (sqlite3_column_type(preparedSQL, 8) != SQLITE_NULL) {
+        mediaForMsg.push_back(Media::fromSQLResult(preparedSQL, 8));
       }
       messages.push_back(std::make_pair(std::move(message), mediaForMsg));
     }
@@ -2671,12 +2701,15 @@
 std::vector<MessageEntity>
 SQLiteQueryExecutor::getRelatedMessages(const std::string &messageID) const {
   static std::string getMessageSQL =
-      "SELECT * "
-      "FROM messages "
+      "SELECT "
+      "  m.id, m.local_id, m.thread, m.user, m.type, m.future_type, "
+      "  m.content, m.time, media.id, media.container, media.thread, "
+      "  media.uri, media.type, media.extras "
+      "FROM messages AS m "
       "LEFT JOIN media "
-      "  ON messages.id = media.container "
-      "WHERE messages.id = ? OR messages.target_message = ? "
-      "ORDER BY messages.time DESC";
+      "  ON m.id = media.container "
+      "WHERE m.id = ? OR m.target_message = ? "
+      "ORDER BY m.time DESC";
   comm::SQLiteStatementWrapper preparedSQL(
       SQLiteQueryExecutor::getConnection(),
       getMessageSQL,
@@ -2753,13 +2786,18 @@
 std::vector<MessageEntity> SQLiteQueryExecutor::getRelatedMessagesForSearch(
     const std::vector<std::string> &messageIDs) const {
   std::stringstream selectRelatedMessagesSQLStream;
-  selectRelatedMessagesSQLStream << "SELECT * "
-                                    "FROM messages "
+  selectRelatedMessagesSQLStream << "SELECT "
+                                    "  m.id, m.local_id, m.thread, m.user, "
+                                    "  m.type, m.future_type, m.content, "
+                                    "  m.time, media.id, media.container, "
+                                    "  media.thread, media.uri, media.type, "
+                                    "  media.extras "
+                                    "FROM messages AS m "
                                     "LEFT JOIN media "
-                                    "  ON messages.id = media.container "
-                                    "WHERE messages.target_message IN "
+                                    "  ON m.id = media.container "
+                                    "WHERE m.target_message IN "
                                  << getSQLStatementArray(messageIDs.size())
-                                 << "ORDER BY messages.time DESC";
+                                 << "ORDER BY m.time DESC";
 
   std::string selectRelatedMessagesSQL = selectRelatedMessagesSQLStream.str();
 
diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h
--- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h
+++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageTypeEnum.h
@@ -2,6 +2,7 @@
 
 namespace comm {
 
+// Should be in sync with lib/types/message-types-enum.js
 enum class MessageType {
   TEXT = 0,
   CREATE_THREAD = 1,
diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/ThreadOperationsUtilities/ThreadTypeEnum.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/ThreadOperationsUtilities/ThreadTypeEnum.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/ThreadOperationsUtilities/ThreadTypeEnum.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#import <vector>
+
+namespace comm {
+
+// Should be in sync with lib/types/thread-types-enum.js
+enum class ThreadType {
+  SIDEBAR = 5,
+  GENESIS_PERSONAL = 6,
+  GENESIS_PRIVATE = 7,
+  COMMUNITY_ROOT = 8,
+  COMMUNITY_ANNOUNCEMENT_ROOT = 9,
+  COMMUNITY_OPEN_SUBTHREAD = 3,
+  COMMUNITY_OPEN_ANNOUNCEMENT_SUBTHREAD = 10,
+  COMMUNITY_SECRET_SUBTHREAD = 4,
+  COMMUNITY_SECRET_ANNOUNCEMENT_SUBTHREAD = 11,
+  GENESIS = 12,
+  LOCAL = 13,
+  PERSONAL = 14,
+  PRIVATE = 15,
+  THICK_SIDEBAR = 16,
+};
+
+const std::vector<ThreadType> THICK_THREAD_TYPES{
+    ThreadType::LOCAL,
+    ThreadType::PERSONAL,
+    ThreadType::PRIVATE,
+    ThreadType::THICK_SIDEBAR};
+
+} // namespace comm
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -145,7 +145,8 @@
       .function("getAllDrafts", &SQLiteQueryExecutor::getAllDrafts)
       .function("removeAllDrafts", &SQLiteQueryExecutor::removeAllDrafts)
       .function("removeDrafts", &SQLiteQueryExecutor::removeDrafts)
-      .function("getInitialMessagesWeb", &SQLiteQueryExecutor::getInitialMessagesWeb)
+      .function(
+          "getInitialMessagesWeb", &SQLiteQueryExecutor::getInitialMessagesWeb)
       .function("removeAllMessages", &SQLiteQueryExecutor::removeAllMessages)
       .function("removeMessages", &SQLiteQueryExecutor::removeMessages)
       .function(
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/web/shared-worker/queries/messages-and-media-queries.test.js b/web/shared-worker/queries/messages-and-media-queries.test.js
--- a/web/shared-worker/queries/messages-and-media-queries.test.js
+++ b/web/shared-worker/queries/messages-and-media-queries.test.js
@@ -1,6 +1,9 @@
 // @flow
 
+import { threadTypes } from 'lib/types/thread-types-enum.js';
+
 import { getDatabaseModule } from '../db-module.js';
+import { createNullableString } from '../types/entities.js';
 import { clearSensitiveData } from '../utils/db-utils.js';
 
 const FILE_PATH = 'test.sqlite';
@@ -83,6 +86,42 @@
       type: 'photo',
       extras: '1',
     });
+    queryExecutor.replaceThreadWeb({
+      id: '1',
+      type: threadTypes.COMMUNITY_OPEN_SUBTHREAD,
+      name: createNullableString(),
+      avatar: createNullableString(),
+      description: createNullableString(),
+      color: 'ffffff',
+      creationTime: '1',
+      parentThreadID: createNullableString(),
+      containingThreadID: createNullableString(),
+      community: createNullableString(),
+      members: '1',
+      roles: '1',
+      currentUser: '{}',
+      sourceMessageID: createNullableString(),
+      repliesCount: 0,
+      pinnedCount: 0,
+    });
+    queryExecutor.replaceThreadWeb({
+      id: '2',
+      type: threadTypes.COMMUNITY_OPEN_SUBTHREAD,
+      name: createNullableString(),
+      avatar: createNullableString(),
+      description: createNullableString(),
+      color: 'ffffff',
+      creationTime: '1',
+      parentThreadID: createNullableString(),
+      containingThreadID: createNullableString(),
+      community: createNullableString(),
+      members: '1',
+      roles: '1',
+      currentUser: '{}',
+      sourceMessageID: createNullableString(),
+      repliesCount: 0,
+      pinnedCount: 0,
+    });
   });
 
   afterEach(() => {
diff --git a/web/shared-worker/types/entities.js b/web/shared-worker/types/entities.js
--- a/web/shared-worker/types/entities.js
+++ b/web/shared-worker/types/entities.js
@@ -179,4 +179,5 @@
   webThreadToClientDBThreadInfo,
   clientDBMessageInfoToWebMessage,
   webMessageToClientDBMessageInfo,
+  createNullableString,
 };