diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js
--- a/lib/reducers/message-reducer.js
+++ b/lib/reducers/message-reducer.js
@@ -607,6 +607,31 @@
     updatedThreads[threadID] = threads[threadID];
   }
 
+  // We don't want to persist an information about startReached for thick
+  // thread containing more than defaultNumberPerThread messages. The reason
+  // is that after closing and reopening the app, we're fetching only a subset
+  // of messages. If we read startReached = true from the DB, we won't attempt
+  // fetching more batches of messages.
+  const dbOps = [
+    ...newMessageOps,
+    {
+      type: 'replace_threads',
+      payload: {
+        threads: Object.fromEntries(
+          Object.entries(updatedThreads).map(([threadID, thread]) => [
+            threadID,
+            threadInfos[threadID].thick
+              ? {
+                  ...thread,
+                  startReached:
+                    thread.messageIDs.length < defaultNumberPerThread,
+                }
+              : thread,
+          ]),
+        ),
+      },
+    },
+  ];
   newMessageOps.push({
     type: 'replace_threads',
     payload: {
@@ -641,10 +666,7 @@
   };
 
   return {
-    messageStoreOperations: [
-      ...updateWithLatestThreadInfosOps,
-      ...newMessageOps,
-    ],
+    messageStoreOperations: [...updateWithLatestThreadInfosOps, ...dbOps],
     messageStore,
   };
 }
diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js
--- a/lib/shared/message-utils.js
+++ b/lib/shared/message-utils.js
@@ -27,17 +27,20 @@
 import { type PlatformDetails } from '../types/device-types.js';
 import type { Media } from '../types/media-types.js';
 import { messageTypes } from '../types/message-types-enum.js';
-import type {
-  ComposableMessageInfo,
-  MessageData,
-  MessageInfo,
-  MessageStore,
-  MultimediaMessageData,
-  RawComposableMessageInfo,
-  RawMessageInfo,
-  RawMultimediaMessageInfo,
-  RobotextMessageInfo,
-  ThreadMessageInfo,
+import {
+  type ComposableMessageInfo,
+  type FetchMessageInfosPayload,
+  type MessageData,
+  type MessageInfo,
+  type MessageStore,
+  type MultimediaMessageData,
+  type RawComposableMessageInfo,
+  type RawMessageInfo,
+  type RawMultimediaMessageInfo,
+  type RobotextMessageInfo,
+  type ThreadMessageInfo,
+  defaultNumberPerThread,
+  messageTruncationStatus,
 } from '../types/message-types.js';
 import type {
   EditMessageInfo,
@@ -56,11 +59,13 @@
 import { threadTypeIsThick } from '../types/thread-types-enum.js';
 import type { LegacyRawThreadInfo } from '../types/thread-types.js';
 import type { UserInfos } from '../types/user-types.js';
+import { getConfig } from '../utils/config.js';
 import {
   type EntityText,
   ET,
   useEntityTextAsString,
 } from '../utils/entity-text.js';
+import { translateClientDBMessageInfoToRawMessageInfo } from '../utils/message-ops-utils.js';
 import { useDispatchActionPromise } from '../utils/redux-promise-utils.js';
 import { useSelector } from '../utils/redux-utils.js';
 
@@ -685,6 +690,29 @@
   return timePerKeyserver;
 }
 
+async function fetchThickThreadMessages(
+  threadID: string,
+  limit: number,
+  offset: number,
+): Promise<FetchMessageInfosPayload> {
+  const { sqliteAPI } = getConfig();
+  const dbMessages = await sqliteAPI.fetchMessages(threadID, limit + 1, offset);
+  const isFetchExhaustive = dbMessages.length !== limit + 1;
+  const messagesToReturn = isFetchExhaustive
+    ? dbMessages
+    : dbMessages.slice(0, -1);
+  const messages = messagesToReturn.map(
+    translateClientDBMessageInfoToRawMessageInfo,
+  );
+  return {
+    threadID,
+    rawMessageInfos: messages,
+    truncationStatus: isFetchExhaustive
+      ? messageTruncationStatus.EXHAUSTIVE
+      : messageTruncationStatus.UNCHANGED,
+  };
+}
+
 function useFetchMessages(threadInfo: ThreadInfo): () => Promise<void> {
   const oldestMessageServerID = useOldestMessageServerID(threadInfo.id);
   const callFetchMessagesBeforeCursor = useFetchMessagesBeforeCursor();
@@ -696,9 +724,25 @@
     registerFetchKey(fetchMostRecentMessagesActionTypes);
   }, []);
 
+  const threadID = threadInfo.id;
+  const messageIDs = useSelector(
+    state => state.messageStore.threads[threadID].messageIDs,
+  );
+
   return React.useCallback(async () => {
-    const threadID = threadInfo.id;
     if (threadTypeIsThick(threadInfo.type)) {
+      const promise = (async () => {
+        const currentNumberOfFetchedMessages = messageIDs?.length ?? 0;
+        return await fetchThickThreadMessages(
+          threadID,
+          defaultNumberPerThread,
+          currentNumberOfFetchedMessages,
+        );
+      })();
+      await dispatchActionPromise(
+        fetchMessagesBeforeCursorActionTypes,
+        promise,
+      );
       return;
     }
     if (oldestMessageServerID) {
@@ -719,8 +763,9 @@
     callFetchMessagesBeforeCursor,
     callFetchMostRecentMessages,
     dispatchActionPromise,
+    messageIDs?.length,
     oldestMessageServerID,
-    threadInfo.id,
+    threadID,
     threadInfo.type,
   ]);
 }