diff --git a/native/android/app/src/main/java/app/comm/android/fbjni/CommMMKV.java b/native/android/app/src/main/java/app/comm/android/fbjni/CommMMKV.java
--- a/native/android/app/src/main/java/app/comm/android/fbjni/CommMMKV.java
+++ b/native/android/app/src/main/java/app/comm/android/fbjni/CommMMKV.java
@@ -20,8 +20,7 @@
   private static String mmkvIdentifier;
 
   private static MMKV getMMKVInstance(String mmkvID, String encryptionKey) {
-    MMKV mmkv =
-        MMKV.mmkvWithID(mmkvID, MMKV.SINGLE_PROCESS_MODE, encryptionKey);
+    MMKV mmkv = MMKV.mmkvWithID(mmkvID, MMKV.MULTI_PROCESS_MODE, encryptionKey);
     if (mmkv == null) {
       throw new RuntimeException("Failed to instantiate MMKV object.");
     }
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
@@ -36,7 +36,7 @@
   const std::string publicCryptoAccountID = "publicCryptoAccountID";
   std::unique_ptr<crypto::CryptoModule> contentCryptoModule;
   const std::string notifsCryptoAccountID = "notifsCryptoAccountID";
-  std::unique_ptr<crypto::CryptoModule> notifsCryptoModule;
+
   DraftStore draftStore;
   ThreadStore threadStore;
   MessageStore messageStore;
@@ -51,8 +51,11 @@
   EntryStore entryStore;
   MessageSearchStore messageSearchStore;
 
-  void
-  persistCryptoModules(bool persistContentModule, bool persistNotifsModule);
+  void persistCryptoModules(
+      bool persistContentModule,
+      std::optional<
+          std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+          maybeUpdatedNotifsCryptoModule);
   jsi::Value createNewBackupInternal(
       jsi::Runtime &rt,
       std::string backupSecret,
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
@@ -561,10 +561,11 @@
 
 void CommCoreModule::persistCryptoModules(
     bool persistContentModule,
-    bool persistNotifsModule) {
+    std::optional<std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+        maybeUpdatedNotifsCryptoModule) {
   std::string storedSecretKey = getAccountDataKey(secureStoreAccountDataKey);
 
-  if (!persistContentModule && !persistNotifsModule) {
+  if (!persistContentModule && !maybeUpdatedNotifsCryptoModule.has_value()) {
     return;
   }
 
@@ -573,11 +574,6 @@
     newContentPersist = this->contentCryptoModule->storeAsB64(storedSecretKey);
   }
 
-  crypto::Persist newNotifsPersist;
-  if (persistNotifsModule) {
-    newNotifsPersist = this->notifsCryptoModule->storeAsB64(storedSecretKey);
-  }
-
   std::promise<void> persistencePromise;
   std::future<void> persistenceFuture = persistencePromise.get_future();
   GlobalDBSingleton::instance.scheduleOrRunCancellable(
@@ -589,10 +585,10 @@
                 DatabaseManager::getQueryExecutor().getContentAccountID(),
                 newContentPersist);
           }
-          if (persistNotifsModule) {
-            DatabaseManager::getQueryExecutor().storeOlmPersistData(
-                DatabaseManager::getQueryExecutor().getNotifsAccountID(),
-                newNotifsPersist);
+          if (maybeUpdatedNotifsCryptoModule.has_value()) {
+            NotificationsCryptoModule::persistNotificationsAccount(
+                maybeUpdatedNotifsCryptoModule.value().first,
+                maybeUpdatedNotifsCryptoModule.value().second);
           }
           DatabaseManager::getQueryExecutor().commitTransaction();
           persistencePromise.set_value();
@@ -644,6 +640,7 @@
             std::optional<std::string> notifsAccountData =
                 DatabaseManager::getQueryExecutor().getOlmPersistAccountData(
                     DatabaseManager::getQueryExecutor().getNotifsAccountID());
+
             if (notifsAccountData.has_value()) {
               notifsPersist.account = crypto::OlmBuffer(
                   notifsAccountData->begin(), notifsAccountData->end());
@@ -660,14 +657,23 @@
                 storedSecretKey.value(),
                 contentPersist));
 
-            this->notifsCryptoModule.reset(new crypto::CryptoModule(
-                this->notifsCryptoAccountID,
-                storedSecretKey.value(),
-                notifsPersist));
+            std::optional<
+                std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+                maybeNotifsCryptoAccountToPersist;
+
+            if (!NotificationsCryptoModule::
+                    isNotificationsAccountInitialized()) {
+              maybeNotifsCryptoAccountToPersist = {
+                  std::make_shared<crypto::CryptoModule>(
+                      this->notifsCryptoAccountID,
+                      storedSecretKey.value(),
+                      notifsPersist),
+                  storedSecretKey.value()};
+            }
 
             try {
               this->persistCryptoModules(
-                  contentPersist.isEmpty(), notifsPersist.isEmpty());
+                  contentPersist.isEmpty(), maybeNotifsCryptoAccountToPersist);
             } catch (const std::exception &e) {
               error = e.what();
             }
@@ -696,12 +702,12 @@
           std::string primaryKeysResult;
           std::string notificationsKeysResult;
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             error = "user has not been initialized";
           } else {
             primaryKeysResult = this->contentCryptoModule->getIdentityKeys();
             notificationsKeysResult =
-                this->notifsCryptoModule->getIdentityKeys();
+                NotificationsCryptoModule::getIdentityKeys();
           }
 
           std::string notificationsCurve25519Cpp, notificationsEd25519Cpp,
@@ -873,7 +879,7 @@
           std::string contentResult;
           std::string notifResult;
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
@@ -883,9 +889,13 @@
             contentResult =
                 this->contentCryptoModule->getOneTimeKeysForPublishing(
                     oneTimeKeysAmount);
-            notifResult = this->notifsCryptoModule->getOneTimeKeysForPublishing(
-                oneTimeKeysAmount);
-            this->persistCryptoModules(true, true);
+            std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>
+                notifsCryptoModuleWithPicklingKey =
+                    NotificationsCryptoModule::fetchNotificationsAccount()
+                        .value();
+            notifResult = notifsCryptoModuleWithPicklingKey.first
+                              ->getOneTimeKeysForPublishing(oneTimeKeysAmount);
+            this->persistCryptoModules(true, notifsCryptoModuleWithPicklingKey);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -918,19 +928,25 @@
           std::optional<std::string> maybeNotifsPrekeyToUpload;
 
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
             return;
           }
 
+          std::optional<
+              std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+              notifsCryptoModuleWithPicklingKey;
           try {
+            notifsCryptoModuleWithPicklingKey =
+                NotificationsCryptoModule::fetchNotificationsAccount();
             maybeContentPrekeyToUpload =
                 this->contentCryptoModule->validatePrekey();
             maybeNotifsPrekeyToUpload =
-                this->notifsCryptoModule->validatePrekey();
-            this->persistCryptoModules(true, true);
+                notifsCryptoModuleWithPicklingKey.value()
+                    .first->validatePrekey();
+            this->persistCryptoModules(true, notifsCryptoModuleWithPicklingKey);
 
             if (!maybeContentPrekeyToUpload.has_value()) {
               maybeContentPrekeyToUpload =
@@ -938,7 +954,8 @@
             }
             if (!maybeNotifsPrekeyToUpload.has_value()) {
               maybeNotifsPrekeyToUpload =
-                  this->notifsCryptoModule->getUnpublishedPrekey();
+                  notifsCryptoModuleWithPicklingKey.value()
+                      .first->getUnpublishedPrekey();
             }
           } catch (const std::exception &e) {
             error = e.what();
@@ -968,7 +985,8 @@
           if (maybeNotifsPrekeyToUpload.has_value()) {
             notifsPrekeyToUpload = maybeNotifsPrekeyToUpload.value();
           } else {
-            notifsPrekeyToUpload = this->notifsCryptoModule->getPrekey();
+            notifsPrekeyToUpload =
+                notifsCryptoModuleWithPicklingKey.value().first->getPrekey();
           }
 
           std::string prekeyUploadError;
@@ -977,7 +995,8 @@
             std::string contentPrekeySignature =
                 this->contentCryptoModule->getPrekeySignature();
             std::string notifsPrekeySignature =
-                this->notifsCryptoModule->getPrekeySignature();
+                notifsCryptoModuleWithPicklingKey.value()
+                    .first->getPrekeySignature();
 
             try {
               std::promise<folly::dynamic> prekeyPromise;
@@ -1010,8 +1029,10 @@
 
             if (!prekeyUploadError.size()) {
               this->contentCryptoModule->markPrekeyAsPublished();
-              this->notifsCryptoModule->markPrekeyAsPublished();
-              this->persistCryptoModules(true, true);
+              notifsCryptoModuleWithPicklingKey.value()
+                  .first->markPrekeyAsPublished();
+              this->persistCryptoModules(
+                  true, notifsCryptoModuleWithPicklingKey);
             }
           } catch (std::exception &e) {
             error = e.what();
@@ -1044,13 +1065,19 @@
           std::optional<std::string> notifPrekeyBlob;
 
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
             return;
           }
+
+          std::optional<
+              std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+              notifsCryptoModuleWithPicklingKey;
           try {
+            notifsCryptoModuleWithPicklingKey =
+                NotificationsCryptoModule::fetchNotificationsAccount();
             contentPrekeyBlob = this->contentCryptoModule->validatePrekey();
             if (!contentPrekeyBlob) {
               contentPrekeyBlob =
@@ -1060,20 +1087,22 @@
               contentPrekeyBlob = this->contentCryptoModule->getPrekey();
             }
 
-            notifPrekeyBlob = this->notifsCryptoModule->validatePrekey();
+            notifPrekeyBlob = notifsCryptoModuleWithPicklingKey.value()
+                                  .first->validatePrekey();
             if (!notifPrekeyBlob) {
-              notifPrekeyBlob =
-                  this->notifsCryptoModule->getUnpublishedPrekey();
+              notifPrekeyBlob = notifsCryptoModuleWithPicklingKey.value()
+                                    .first->getUnpublishedPrekey();
             }
             if (!notifPrekeyBlob) {
-              notifPrekeyBlob = this->notifsCryptoModule->getPrekey();
+              notifPrekeyBlob =
+                  notifsCryptoModuleWithPicklingKey.value().first->getPrekey();
             }
-            this->persistCryptoModules(true, true);
+            this->persistCryptoModules(true, notifsCryptoModuleWithPicklingKey);
 
             contentPrekeySignature =
                 this->contentCryptoModule->getPrekeySignature();
-            notifPrekeySignature =
-                this->notifsCryptoModule->getPrekeySignature();
+            notifPrekeySignature = notifsCryptoModuleWithPicklingKey.value()
+                                       .first->getPrekeySignature();
 
             contentPrekey = parseOLMPrekey(contentPrekeyBlob.value());
             notifPrekey = parseOLMPrekey(notifPrekeyBlob.value());
@@ -1135,36 +1164,45 @@
         taskType job = [=, &innerRt]() {
           std::string error;
           crypto::EncryptedData result;
+          std::optional<
+              std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+              notifsCryptoModuleWithPicklingKey;
           try {
+            notifsCryptoModuleWithPicklingKey =
+                NotificationsCryptoModule::fetchNotificationsAccount();
             std::optional<crypto::OlmBuffer> oneTimeKeyBuffer;
             if (oneTimeKeyCpp) {
               oneTimeKeyBuffer = crypto::OlmBuffer(
                   oneTimeKeyCpp->begin(), oneTimeKeyCpp->end());
             }
 
-            this->notifsCryptoModule->initializeOutboundForSendingSession(
-                keyserverIDCpp,
-                std::vector<uint8_t>(
-                    identityKeysCpp.begin(), identityKeysCpp.end()),
-                std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
-                std::vector<uint8_t>(
-                    prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
-                oneTimeKeyBuffer);
+            notifsCryptoModuleWithPicklingKey.value()
+                .first->initializeOutboundForSendingSession(
+                    keyserverIDCpp,
+                    std::vector<uint8_t>(
+                        identityKeysCpp.begin(), identityKeysCpp.end()),
+                    std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
+                    std::vector<uint8_t>(
+                        prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
+                    oneTimeKeyBuffer);
 
-            result = this->notifsCryptoModule->encrypt(
+            result = notifsCryptoModuleWithPicklingKey.value().first->encrypt(
                 keyserverIDCpp,
                 NotificationsCryptoModule::initialEncryptedMessageContent);
 
             std::shared_ptr<crypto::Session> keyserverNotificationsSession =
-                this->notifsCryptoModule->getSessionByDeviceId(keyserverIDCpp);
+                notifsCryptoModuleWithPicklingKey.value()
+                    .first->getSessionByDeviceId(keyserverIDCpp);
 
             NotificationsCryptoModule::persistNotificationsSession(
                 keyserverIDCpp, keyserverNotificationsSession);
 
             // Session is removed from the account since it is persisted
             // at different location that the account after serialization
-            this->notifsCryptoModule->removeSessionByDeviceId(keyserverIDCpp);
-            this->persistCryptoModules(false, true);
+            notifsCryptoModuleWithPicklingKey.value()
+                .first->removeSessionByDeviceId(keyserverIDCpp);
+            this->persistCryptoModules(
+                false, notifsCryptoModuleWithPicklingKey);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -1215,7 +1253,7 @@
       rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         taskType job = [=, &innerRt]() {
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
@@ -1257,7 +1295,7 @@
       rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         taskType job = [=, &innerRt]() {
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
@@ -1469,7 +1507,7 @@
             initialEncryptedData =
                 contentCryptoModule->encrypt(deviceIDCpp, initMessage);
 
-            this->persistCryptoModules(true, false);
+            this->persistCryptoModules(true, std::nullopt);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -1526,7 +1564,7 @@
                 messageType};
             decryptedMessage =
                 this->contentCryptoModule->decrypt(deviceIDCpp, encryptedData);
-            this->persistCryptoModules(true, false);
+            this->persistCryptoModules(true, std::nullopt);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -1554,7 +1592,7 @@
           bool result;
 
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
@@ -1601,35 +1639,44 @@
         taskType job = [=, &innerRt]() {
           std::string error;
           crypto::EncryptedData result;
+          std::optional<
+              std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+              notifsCryptoModuleWithPicklingKey;
           try {
+            notifsCryptoModuleWithPicklingKey =
+                NotificationsCryptoModule::fetchNotificationsAccount();
             std::optional<crypto::OlmBuffer> oneTimeKeyBuffer;
             if (oneTimeKeyCpp) {
               oneTimeKeyBuffer = crypto::OlmBuffer(
                   oneTimeKeyCpp->begin(), oneTimeKeyCpp->end());
             }
-            this->notifsCryptoModule->initializeOutboundForSendingSession(
-                deviceIDCpp,
-                std::vector<uint8_t>(
-                    identityKeysCpp.begin(), identityKeysCpp.end()),
-                std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
-                std::vector<uint8_t>(
-                    prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
-                oneTimeKeyBuffer);
+            notifsCryptoModuleWithPicklingKey.value()
+                .first->initializeOutboundForSendingSession(
+                    deviceIDCpp,
+                    std::vector<uint8_t>(
+                        identityKeysCpp.begin(), identityKeysCpp.end()),
+                    std::vector<uint8_t>(prekeyCpp.begin(), prekeyCpp.end()),
+                    std::vector<uint8_t>(
+                        prekeySignatureCpp.begin(), prekeySignatureCpp.end()),
+                    oneTimeKeyBuffer);
 
-            result = this->notifsCryptoModule->encrypt(
+            result = notifsCryptoModuleWithPicklingKey.value().first->encrypt(
                 deviceIDCpp,
                 NotificationsCryptoModule::initialEncryptedMessageContent);
 
             std::shared_ptr<crypto::Session> peerNotificationsSession =
-                this->notifsCryptoModule->getSessionByDeviceId(deviceIDCpp);
+                notifsCryptoModuleWithPicklingKey.value()
+                    .first->getSessionByDeviceId(deviceIDCpp);
 
             NotificationsCryptoModule::persistDeviceNotificationsSession(
                 deviceIDCpp, peerNotificationsSession);
 
             // Session is removed from the account since it is persisted
             // at different location that the account after serialization
-            this->notifsCryptoModule->removeSessionByDeviceId(deviceIDCpp);
-            this->persistCryptoModules(false, true);
+            notifsCryptoModuleWithPicklingKey.value()
+                .first->removeSessionByDeviceId(deviceIDCpp);
+            this->persistCryptoModules(
+                false, notifsCryptoModuleWithPicklingKey);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -1660,7 +1707,7 @@
           try {
             encryptedMessage =
                 contentCryptoModule->encrypt(deviceIDCpp, messageCpp);
-            this->persistCryptoModules(true, false);
+            this->persistCryptoModules(true, std::nullopt);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -1802,7 +1849,7 @@
                 messageType};
             decryptedMessage =
                 this->contentCryptoModule->decrypt(deviceIDCpp, encryptedData);
-            this->persistCryptoModules(true, false);
+            this->persistCryptoModules(true, std::nullopt);
           } catch (const std::exception &e) {
             error = e.what();
           }
@@ -2849,17 +2896,23 @@
           std::string error;
 
           if (this->contentCryptoModule == nullptr ||
-              this->notifsCryptoModule == nullptr) {
+              !NotificationsCryptoModule::isNotificationsAccountInitialized()) {
             this->jsInvoker_->invokeAsync([=, &innerRt]() {
               promise->reject("user has not been initialized");
             });
             return;
           }
 
+          std::optional<
+              std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+              notifsCryptoModuleWithPicklingKey;
           try {
+            notifsCryptoModuleWithPicklingKey =
+                NotificationsCryptoModule::fetchNotificationsAccount();
             this->contentCryptoModule->markPrekeyAsPublished();
-            this->notifsCryptoModule->markPrekeyAsPublished();
-            this->persistCryptoModules(true, true);
+            notifsCryptoModuleWithPicklingKey.value()
+                .first->markPrekeyAsPublished();
+            this->persistCryptoModules(true, notifsCryptoModuleWithPicklingKey);
           } catch (std::exception &e) {
             error = e.what();
           }
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h
@@ -45,6 +45,8 @@
   const static int olmEncryptedTypeMessage;
 
   static void clearSensitiveData();
+
+  // notifications sessions
   static void persistNotificationsSession(
       const std::string &keyserverID,
       std::shared_ptr<crypto::Session> keyserverNotificationsSession);
@@ -58,6 +60,16 @@
   isNotificationsSessionInitializedWithDevices(
       const std::vector<std::string> &deviceIDs);
 
+  // notifications account
+  static void persistNotificationsAccount(
+      const std::shared_ptr<crypto::CryptoModule> cryptoModule,
+      const std::string &picklingKey);
+  static std::optional<
+      std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+  fetchNotificationsAccount();
+  static bool isNotificationsAccountInitialized();
+  static std::string getIdentityKeys();
+
   class BaseStatefulDecryptResult {
     BaseStatefulDecryptResult(
         std::string picklingKey,
diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
@@ -38,6 +38,7 @@
 const std::string ashoatKeyserverIDUsedOnlyForMigrationFromLegacyNotifStorage =
     "256";
 const int temporaryFilePathRandomSuffixLength = 32;
+const std::string notificationsAccountKey = "NOTIFS.ACCOUNT";
 
 std::unique_ptr<crypto::CryptoModule>
 NotificationsCryptoModule::deserializeCryptoModule(
@@ -268,6 +269,62 @@
       serializedSession.value());
 }
 
+void NotificationsCryptoModule::persistNotificationsAccount(
+    const std::shared_ptr<crypto::CryptoModule> cryptoModule,
+    const std::string &picklingKey) {
+  crypto::Persist serializedCryptoModule =
+      cryptoModule->storeAsB64(picklingKey);
+  crypto::OlmBuffer serializedAccount = serializedCryptoModule.account;
+  std::string serializedAccountString{
+      serializedAccount.begin(), serializedAccount.end()};
+
+  folly::dynamic serializedAccountObject = folly::dynamic::object(
+      "account", serializedAccountString)("picklingKey", picklingKey);
+  std::string serializedAccountJson = folly::toJson(serializedAccountObject);
+
+  bool accountPersisted =
+      CommMMKV::setString(notificationsAccountKey, serializedAccountJson);
+
+  if (!accountPersisted) {
+    throw std::runtime_error("Failed to persist notifications crypto account.");
+  }
+}
+
+std::optional<std::pair<std::shared_ptr<crypto::CryptoModule>, std::string>>
+NotificationsCryptoModule::fetchNotificationsAccount() {
+  std::optional<std::string> serializedAccountJson;
+  try {
+    serializedAccountJson = CommMMKV::getString(notificationsAccountKey);
+  } catch (const CommMMKV::InitFromNSEForbiddenError &e) {
+    serializedAccountJson = std::nullopt;
+  }
+
+  if (!serializedAccountJson.has_value()) {
+    return std::nullopt;
+  }
+
+  folly::dynamic serializedAccountObject;
+  try {
+    serializedAccountObject = folly::parseJson(serializedAccountJson.value());
+  } catch (const folly::json::parse_error &e) {
+    throw std::runtime_error(
+        "Notifications account deserialization failed with reason: " +
+        std::string(e.what()));
+  }
+
+  std::string picklingKey = serializedAccountObject["picklingKey"].asString();
+  std::string accountString = serializedAccountObject["account"].asString();
+  crypto::OlmBuffer account =
+      crypto::OlmBuffer{accountString.begin(), accountString.end()};
+  crypto::Persist serializedCryptoModule{account, {}};
+
+  std::shared_ptr<crypto::CryptoModule> cryptoModule =
+      std::make_shared<crypto::CryptoModule>(
+          notificationsCryptoAccountID, picklingKey, serializedCryptoModule);
+
+  return {{cryptoModule, picklingKey}};
+}
+
 void NotificationsCryptoModule::persistNotificationsSession(
     const std::string &keyserverID,
     std::shared_ptr<crypto::Session> keyserverNotificationsSession) {
@@ -317,6 +374,20 @@
 
   return result;
 }
+// notifications account
+
+bool NotificationsCryptoModule::isNotificationsAccountInitialized() {
+  return fetchNotificationsAccount().has_value();
+}
+
+std::string NotificationsCryptoModule::getIdentityKeys() {
+  auto cryptoModuleWithPicklingKey =
+      NotificationsCryptoModule::fetchNotificationsAccount();
+  if (!cryptoModuleWithPicklingKey.has_value()) {
+    throw std::runtime_error("Notifications crypto account not initialized.");
+  }
+  return cryptoModuleWithPicklingKey.value().first->getIdentityKeys();
+}
 
 NotificationsCryptoModule::BaseStatefulDecryptResult::BaseStatefulDecryptResult(
     std::string picklingKey,