diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
@@ -4,6 +4,7 @@
 #include "entities/Draft.h"
 #include "entities/Media.h"
 #include "entities/Message.h"
+#include "entities/MessageStoreThread.h"
 #include "entities/OlmPersistAccount.h"
 #include "entities/OlmPersistSession.h"
 #include "entities/Thread.h"
@@ -43,6 +44,11 @@
   virtual void replaceMessage(const Message &message) const = 0;
   virtual void rekeyMessage(std::string from, std::string to) const = 0;
   virtual void removeAllMedia() const = 0;
+  virtual void replaceMessageStoreThreads(
+      const std::vector<MessageStoreThread> &threads) const = 0;
+  virtual void
+  removeMessageStoreThreads(const std::vector<std::string> &ids) const = 0;
+  virtual void removeAllMessageStoreThreads() const = 0;
   virtual void
   removeMediaForMessages(const std::vector<std::string> &msg_ids) const = 0;
   virtual void removeMediaForMessage(std::string msg_id) const = 0;
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
@@ -41,6 +41,11 @@
       const std::vector<std::string> &threadIDs) const override;
   void replaceMessage(const Message &message) const override;
   void rekeyMessage(std::string from, std::string to) const override;
+  void replaceMessageStoreThreads(
+      const std::vector<MessageStoreThread> &threads) const override;
+  void
+  removeMessageStoreThreads(const std::vector<std::string> &ids) const override;
+  void removeAllMessageStoreThreads() const override;
   void removeAllMedia() const override;
   void removeMediaForMessages(
       const std::vector<std::string> &msg_ids) const override;
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
@@ -364,6 +364,17 @@
   return false;
 }
 
+bool create_message_store_threads_table(sqlite3 *db) {
+  std::string query =
+      "CREATE TABLE IF NOT EXISTS message_store_threads ("
+      "	 id TEXT UNIQUE PRIMARY KEY NOT NULL,"
+      "	 start_reached INTEGER NOT NULL,"
+      "	 last_navigated_to BIGINT NOT NULL,"
+      "	 last_pruned BIGINT NOT NULL"
+      ");";
+  return create_table(db, query, "message_store_threads");
+}
+
 bool create_schema(sqlite3 *db) {
   char *error;
   sqlite3_exec(
@@ -427,6 +438,13 @@
       "	 data TEXT NOT NULL"
       ");"
 
+      "CREATE TABLE IF NOT EXISTS message_store_threads ("
+      "	 id TEXT UNIQUE PRIMARY KEY NOT NULL,"
+      "	 start_reached INTEGER NOT NULL,"
+      "	 last_navigated_to BIGINT NOT NULL,"
+      "	 last_pruned BIGINT NOT NULL"
+      ");"
+
       "CREATE INDEX IF NOT EXISTS media_idx_container"
       "  ON media (container);"
 
@@ -663,7 +681,8 @@
      {24, {add_not_null_constraint_to_drafts, true}},
      {25, {add_not_null_constraint_to_metadata, true}},
      {26, {add_avatar_column_to_threads_table, true}},
-     {27, {add_pinned_count_column_to_threads, true}}}};
+     {27, {add_pinned_count_column_to_threads, true}},
+     {28, {create_message_store_threads_table, true}}}};
 
 enum class MigrationResult { SUCCESS, FAILURE, NOT_APPLIED };
 
@@ -870,7 +889,14 @@
       make_table(
           "metadata",
           make_column("name", &Metadata::name, unique(), primary_key()),
-          make_column("data", &Metadata::data)));
+          make_column("data", &Metadata::data)),
+      make_table(
+          "message_store_threads",
+          make_column("id", &MessageStoreThread::id, unique(), primary_key()),
+          make_column("start_reached", &MessageStoreThread::start_reached),
+          make_column(
+              "last_navigated_to", &MessageStoreThread::last_navigated_to),
+          make_column("last_pruned", &MessageStoreThread::last_pruned)));
   storage.on_open = on_database_open;
   return storage;
 }
@@ -1057,6 +1083,23 @@
       set(c(&Media::container) = to), where(c(&Media::container) == from));
 }
 
+void SQLiteQueryExecutor::replaceMessageStoreThreads(
+    const std::vector<MessageStoreThread> &threads) const {
+  for (auto &thread : threads) {
+    SQLiteQueryExecutor::getStorage().replace(thread);
+  }
+}
+
+void SQLiteQueryExecutor::removeAllMessageStoreThreads() const {
+  SQLiteQueryExecutor::getStorage().remove_all<MessageStoreThread>();
+}
+
+void SQLiteQueryExecutor::removeMessageStoreThreads(
+    const std::vector<std::string> &ids) const {
+  SQLiteQueryExecutor::getStorage().remove_all<MessageStoreThread>(
+      where(in(&MessageStoreThread::id, ids)));
+}
+
 std::vector<Thread> SQLiteQueryExecutor::getAllThreads() const {
   return SQLiteQueryExecutor::getStorage().get_all<Thread>();
 };
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/MessageStoreThread.h b/native/cpp/CommonCpp/DatabaseManagers/entities/MessageStoreThread.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/MessageStoreThread.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <string>
+
+namespace comm {
+
+struct MessageStoreThread {
+  std::string id;
+  int start_reached;
+  int64_t last_navigated_to;
+  int64_t last_pruned;
+};
+
+} // namespace comm