diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../CryptoTools/CryptoModule.h"
+#include "../Tools/CommMMKV.h"
 #include "../Tools/CommSecureStore.h"
 #include "../Tools/WorkerThread.h"
 #include "../_generated/commJSI.h"
@@ -93,6 +94,15 @@
       jsi::String keyserverID) override;
   virtual jsi::Value
   isNotificationsSessionInitialized(jsi::Runtime &rt) override;
+  virtual jsi::Value updateKeyserverDataInNotifStorage(
+      jsi::Runtime &rt,
+      jsi::Array keyserversData) override;
+  virtual jsi::Value removeKeyserverDataFromNotifStorage(
+      jsi::Runtime &rt,
+      jsi::Array keyserverIDsToDelete) override;
+  virtual jsi::Value getKeyserverDataFromNotifStorage(
+      jsi::Runtime &rt,
+      jsi::Array keyserverIDs) override;
   virtual jsi::Value initializeContentOutboundSession(
       jsi::Runtime &rt,
       jsi::String identityKeys,
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
@@ -874,6 +874,135 @@
       });
 }
 
+jsi::Value CommCoreModule::updateKeyserverDataInNotifStorage(
+    jsi::Runtime &rt,
+    jsi::Array keyserversData) {
+
+  std::vector<std::pair<std::string, int>> keyserversDataCpp;
+  for (auto idx = 0; idx < keyserversData.size(rt); idx++) {
+    auto data = keyserversData.getValueAtIndex(rt, idx).asObject(rt);
+    std::string keyserverID = data.getProperty(rt, "id").asString(rt).utf8(rt);
+    std::string keyserverUnreadCountKey =
+        "KEYSERVER." + keyserverID + ".UNREAD_COUNT";
+    int unreadCount = data.getProperty(rt, "unreadCount").asNumber();
+    keyserversDataCpp.push_back({keyserverUnreadCountKey, unreadCount});
+  }
+
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        std::string error;
+        try {
+          for (const auto &keyserverData : keyserversDataCpp) {
+            CommMMKV::setInt(keyserverData.first, keyserverData.second);
+          }
+        } catch (const std::exception &e) {
+          error = e.what();
+        }
+
+        this->jsInvoker_->invokeAsync([=, &innerRt]() {
+          if (error.size()) {
+            promise->reject(error);
+            return;
+          }
+          promise->resolve(jsi::Value::undefined());
+        });
+      });
+}
+
+jsi::Value CommCoreModule::removeKeyserverDataFromNotifStorage(
+    jsi::Runtime &rt,
+    jsi::Array keyserverIDsToDelete) {
+  std::vector<std::string> keyserverIDsToDeleteCpp{};
+  for (auto idx = 0; idx < keyserverIDsToDelete.size(rt); idx++) {
+    std::string keyserverID =
+        keyserverIDsToDelete.getValueAtIndex(rt, idx).asString(rt).utf8(rt);
+    std::string keyserverUnreadCountKey =
+        "KEYSERVER." + keyserverID + ".UNREAD_COUNT";
+    keyserverIDsToDeleteCpp.push_back(keyserverUnreadCountKey);
+  }
+
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        std::string error;
+        try {
+          CommMMKV::removeKeys(keyserverIDsToDeleteCpp);
+        } catch (const std::exception &e) {
+          error = e.what();
+        }
+
+        this->jsInvoker_->invokeAsync([=, &innerRt]() {
+          if (error.size()) {
+            promise->reject(error);
+            return;
+          }
+          promise->resolve(jsi::Value::undefined());
+        });
+      });
+}
+
+jsi::Value CommCoreModule::getKeyserverDataFromNotifStorage(
+    jsi::Runtime &rt,
+    jsi::Array keyserverIDs) {
+  std::vector<std::string> keyserverIDsCpp{};
+  for (auto idx = 0; idx < keyserverIDs.size(rt); idx++) {
+    std::string keyserverID =
+        keyserverIDs.getValueAtIndex(rt, idx).asString(rt).utf8(rt);
+    keyserverIDsCpp.push_back(keyserverID);
+  }
+
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        std::string error;
+        std::vector<std::pair<std::string, int>> keyserversDataVector{};
+
+        try {
+          for (const auto &keyserverID : keyserverIDsCpp) {
+            std::string keyserverUnreadCountKey =
+                "KEYSERVER." + keyserverID + ".UNREAD_COUNT";
+            std::optional<int> unreadCount =
+                CommMMKV::getInt(keyserverUnreadCountKey, -1);
+
+            if (!unreadCount.has_value()) {
+              continue;
+            }
+
+            keyserversDataVector.push_back({keyserverID, unreadCount.value()});
+          }
+        } catch (const std::exception &e) {
+          error = e.what();
+        }
+
+        auto keyserversDataVectorPtr =
+            std::make_shared<std::vector<std::pair<std::string, int>>>(
+                std::move(keyserversDataVector));
+
+        this->jsInvoker_->invokeAsync(
+            [&innerRt, keyserversDataVectorPtr, error, promise]() {
+              if (error.size()) {
+                promise->reject(error);
+                return;
+              }
+
+              size_t numKeyserversData = keyserversDataVectorPtr->size();
+              jsi::Array jsiKeyserversData =
+                  jsi::Array(innerRt, numKeyserversData);
+              size_t writeIdx = 0;
+
+              for (const auto &keyserverData : *keyserversDataVectorPtr) {
+                jsi::Object jsiKeyserverData = jsi::Object(innerRt);
+                jsiKeyserverData.setProperty(
+                    innerRt, "id", keyserverData.first);
+                jsiKeyserverData.setProperty(
+                    innerRt, "unreadCount", keyserverData.second);
+                jsiKeyserversData.setValueAtIndex(
+                    innerRt, writeIdx++, jsiKeyserverData);
+              }
+
+              promise->resolve(std::move(jsiKeyserversData));
+            });
+      });
+}
+
 jsi::Value CommCoreModule::initializeContentOutboundSession(
     jsi::Runtime &rt,
     jsi::String identityKeys,
diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
--- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
@@ -87,6 +87,15 @@
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->isNotificationsSessionInitialized(rt);
 }
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_updateKeyserverDataInNotifStorage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->updateKeyserverDataInNotifStorage(rt, args[0].asObject(rt).asArray(rt));
+}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_removeKeyserverDataFromNotifStorage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->removeKeyserverDataFromNotifStorage(rt, args[0].asObject(rt).asArray(rt));
+}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getKeyserverDataFromNotifStorage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->getKeyserverDataFromNotifStorage(rt, args[0].asObject(rt).asArray(rt));
+}
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->initializeContentOutboundSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt));
 }
@@ -190,6 +199,9 @@
   methodMap_["validateAndUploadPrekeys"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys};
   methodMap_["initializeNotificationsSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession};
   methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized};
+  methodMap_["updateKeyserverDataInNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_updateKeyserverDataInNotifStorage};
+  methodMap_["removeKeyserverDataFromNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_removeKeyserverDataFromNotifStorage};
+  methodMap_["getKeyserverDataFromNotifStorage"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getKeyserverDataFromNotifStorage};
   methodMap_["initializeContentOutboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession};
   methodMap_["initializeContentInboundSession"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentInboundSession};
   methodMap_["encrypt"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_encrypt};
diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h
--- a/native/cpp/CommonCpp/_generated/commJSI.h
+++ b/native/cpp/CommonCpp/_generated/commJSI.h
@@ -44,6 +44,9 @@
   virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) = 0;
   virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKey, jsi::String keyserverID) = 0;
   virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0;
+  virtual jsi::Value updateKeyserverDataInNotifStorage(jsi::Runtime &rt, jsi::Array keyserversData) = 0;
+  virtual jsi::Value removeKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDsToDelete) = 0;
+  virtual jsi::Value getKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDs) = 0;
   virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKey, jsi::String deviceID) = 0;
   virtual jsi::Value initializeContentInboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String encryptedMessage, jsi::String deviceID) = 0;
   virtual jsi::Value encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) = 0;
@@ -281,6 +284,30 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::isNotificationsSessionInitialized, jsInvoker_, instance_);
     }
+    jsi::Value updateKeyserverDataInNotifStorage(jsi::Runtime &rt, jsi::Array keyserversData) override {
+      static_assert(
+          bridging::getParameterCount(&T::updateKeyserverDataInNotifStorage) == 2,
+          "Expected updateKeyserverDataInNotifStorage(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::updateKeyserverDataInNotifStorage, jsInvoker_, instance_, std::move(keyserversData));
+    }
+    jsi::Value removeKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDsToDelete) override {
+      static_assert(
+          bridging::getParameterCount(&T::removeKeyserverDataFromNotifStorage) == 2,
+          "Expected removeKeyserverDataFromNotifStorage(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::removeKeyserverDataFromNotifStorage, jsInvoker_, instance_, std::move(keyserverIDsToDelete));
+    }
+    jsi::Value getKeyserverDataFromNotifStorage(jsi::Runtime &rt, jsi::Array keyserverIDs) override {
+      static_assert(
+          bridging::getParameterCount(&T::getKeyserverDataFromNotifStorage) == 2,
+          "Expected getKeyserverDataFromNotifStorage(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::getKeyserverDataFromNotifStorage, jsInvoker_, instance_, std::move(keyserverIDs));
+    }
     jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKey, jsi::String deviceID) override {
       static_assert(
           bridging::getParameterCount(&T::initializeContentOutboundSession) == 6,
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -91,6 +91,15 @@
     keyserverID: string,
   ) => Promise<string>;
   +isNotificationsSessionInitialized: () => Promise<boolean>;
+  +updateKeyserverDataInNotifStorage: (
+    keyserversData: $ReadOnlyArray<{ +id: string, +unreadCount: number }>,
+  ) => Promise<void>;
+  +removeKeyserverDataFromNotifStorage: (
+    keyserverIDsToDelete: $ReadOnlyArray<string>,
+  ) => Promise<void>;
+  +getKeyserverDataFromNotifStorage: (
+    keyserverIDs: $ReadOnlyArray<string>,
+  ) => Promise<$ReadOnlyArray<{ +id: string, +unreadCount: number }>>;
   +initializeContentOutboundSession: (
     identityKeys: string,
     prekey: string,