diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
index 49538aade..87d19d549 100644
--- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
+++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
@@ -1,251 +1,252 @@
 #include "NotificationsCryptoModule.h"
 #include "../../CryptoTools/Persist.h"
 #include "../../CryptoTools/Tools.h"
 #include "../../Tools/CommSecureStore.h"
 #include "../../Tools/PlatformSpecificTools.h"
 
 #include <fcntl.h>
 #include <folly/String.h>
 #include <folly/dynamic.h>
 #include <folly/json.h>
 #include <unistd.h>
 #include <fstream>
 #include <sstream>
 
 namespace comm {
 
 const std::string
     NotificationsCryptoModule::secureStoreNotificationsAccountDataKey =
         "notificationsCryptoAccountDataKey";
 const std::string NotificationsCryptoModule::notificationsCryptoAccountID =
     "notificationsCryptoAccountDataID";
 const std::string NotificationsCryptoModule::keyserverHostedNotificationsID =
     "keyserverHostedNotificationsID";
 const std::string NotificationsCryptoModule::initialEncryptedMessageContent =
     "{\"type\": \"init\"}";
 const int NotificationsCryptoModule::olmEncryptedTypeMessage = 1;
+const int temporaryFilePathRandomSuffixLength = 32;
 
 crypto::CryptoModule NotificationsCryptoModule::deserializeCryptoModule(
     const std::string &path,
     const std::string &picklingKey) {
   std::ifstream pickledPersistStream(path, std::ifstream::in);
   if (!pickledPersistStream.good()) {
     throw std::runtime_error(
         "Attempt to deserialize non-existing notifications crypto account");
   }
   std::stringstream pickledPersistStringStream;
   pickledPersistStringStream << pickledPersistStream.rdbuf();
   pickledPersistStream.close();
   std::string pickledPersist = pickledPersistStringStream.str();
 
   folly::dynamic persistJSON;
   try {
     persistJSON = folly::parseJson(pickledPersist);
   } catch (const folly::json::parse_error &e) {
     throw std::runtime_error(
         "Notifications crypto account JSON deserialization failed with "
         "reason: " +
         std::string(e.what()));
   }
 
   std::string accountString = persistJSON["account"].asString();
   crypto::OlmBuffer account =
       std::vector<uint8_t>(accountString.begin(), accountString.end());
   std::unordered_map<std::string, crypto::OlmBuffer> sessions;
 
   if (persistJSON["sessions"].isNull()) {
     return crypto::CryptoModule{
         notificationsCryptoAccountID, picklingKey, {account, sessions}};
   }
   for (auto &sessionKeyValuePair : persistJSON["sessions"].items()) {
     std::string targetUserID = sessionKeyValuePair.first.asString();
     std::string sessionData = sessionKeyValuePair.second.asString();
     sessions[targetUserID] =
         std::vector<uint8_t>(sessionData.begin(), sessionData.end());
   }
   return crypto::CryptoModule{
       notificationsCryptoAccountID, picklingKey, {account, sessions}};
 }
 
 void NotificationsCryptoModule::serializeAndFlushCryptoModule(
     crypto::CryptoModule &cryptoModule,
     const std::string &path,
     const std::string &picklingKey,
     const std::string &callingProcessName) {
   crypto::Persist persist = cryptoModule.storeAsB64(picklingKey);
 
   folly::dynamic sessions = folly::dynamic::object;
   for (auto &sessionKeyValuePair : persist.sessions) {
     std::string targetUserID = sessionKeyValuePair.first;
     crypto::OlmBuffer sessionData = sessionKeyValuePair.second;
     sessions[targetUserID] =
         std::string(sessionData.begin(), sessionData.end());
   }
 
   std::string account =
       std::string(persist.account.begin(), persist.account.end());
   folly::dynamic persistJSON =
       folly::dynamic::object("account", account)("sessions", sessions);
   std::string pickledPersist = folly::toJson(persistJSON);
 
-  std::string temporaryPath = path + callingProcessName;
-  // This is for the case if any of the steps below failed/app was killed
-  // in a previous call to this method leaving temporary file unremoved.
-  // We supply `callingProcessName` as function argument in order to name
-  // temporary file in a deterministic way. Otherwise we would need to use
-  // directory search API to retrieve unremoved files paths.
-  remove(temporaryPath.c_str());
+  std::string temporaryFilePathRandomSuffix =
+      crypto::Tools::generateRandomHexString(
+          temporaryFilePathRandomSuffixLength);
+  std::string temporaryPath =
+      path + callingProcessName + temporaryFilePathRandomSuffix;
+
   mode_t readWritePermissionsMode = 0666;
   int temporaryFD =
       open(temporaryPath.c_str(), O_CREAT | O_WRONLY, readWritePermissionsMode);
   if (temporaryFD == -1) {
     throw std::runtime_error(
         "Failed to create temporary file. Unable to atomically update "
         "notifications crypto account. Details: " +
         std::string(strerror(errno)));
   }
   ssize_t bytesWritten =
       write(temporaryFD, pickledPersist.c_str(), pickledPersist.length());
   if (bytesWritten == -1 || bytesWritten != pickledPersist.length()) {
     remove(temporaryPath.c_str());
     throw std::runtime_error(
         "Failed to write all data to temporary file. Unable to atomically "
         "update notifications crypto account. Details: " +
         std::string(strerror(errno)));
   }
   if (fsync(temporaryFD) == -1) {
     remove(temporaryPath.c_str());
     throw std::runtime_error(
         "Failed to synchronize temporary file data with hardware storage. "
         "Unable to atomically update notifications crypto account. Details: " +
         std::string(strerror(errno)));
   };
   close(temporaryFD);
   if (rename(temporaryPath.c_str(), path.c_str()) == -1) {
     remove(temporaryPath.c_str());
     throw std::runtime_error(
         "Failed to replace temporary file content with notifications crypto "
         "account. Unable to atomically update notifications crypto account. "
         "Details: " +
         std::string(strerror(errno)));
   }
+  remove(temporaryPath.c_str());
 }
 
 void NotificationsCryptoModule::callCryptoModule(
     std::function<void(crypto::CryptoModule &cryptoModule)> caller,
     const std::string &callingProcessName) {
   CommSecureStore secureStore{};
   folly::Optional<std::string> picklingKey = secureStore.get(
       NotificationsCryptoModule::secureStoreNotificationsAccountDataKey);
   if (!picklingKey.hasValue()) {
     throw std::runtime_error(
         "Attempt to retrieve notifications crypto account before it was "
         "correctly initialized.");
   }
 
   const std::string path =
       PlatformSpecificTools::getNotificationsCryptoAccountPath();
   crypto::CryptoModule cryptoModule =
       NotificationsCryptoModule::deserializeCryptoModule(
           path, picklingKey.value());
   caller(cryptoModule);
   NotificationsCryptoModule::serializeAndFlushCryptoModule(
       cryptoModule, path, picklingKey.value(), callingProcessName);
 }
 
 void NotificationsCryptoModule::initializeNotificationsCryptoAccount(
     const std::string &callingProcessName) {
   const std::string notificationsCryptoAccountPath =
       PlatformSpecificTools::getNotificationsCryptoAccountPath();
   std::ifstream notificationCryptoAccountCheck(notificationsCryptoAccountPath);
   if (notificationCryptoAccountCheck.good()) {
     // Implemented in CommmCoreModule semantics regarding public olm account
     // initialization is idempotent. We should follow the same approach when it
     // comes to notifications
     notificationCryptoAccountCheck.close();
     return;
   }
   // There is no reason to check if the key is already present since if we are
   // in this place in the code we are about to create new account
   CommSecureStore secureStore{};
   std::string picklingKey = crypto::Tools::generateRandomString(64);
   secureStore.set(
       NotificationsCryptoModule::secureStoreNotificationsAccountDataKey,
       picklingKey);
 
   crypto::CryptoModule cryptoModule{
       NotificationsCryptoModule::notificationsCryptoAccountID};
   NotificationsCryptoModule::serializeAndFlushCryptoModule(
       cryptoModule,
       notificationsCryptoAccountPath,
       picklingKey,
       callingProcessName);
 }
 
 std::string NotificationsCryptoModule::getNotificationsIdentityKeys(
     const std::string &callingProcessName) {
   std::string identityKeys;
   auto caller = [&identityKeys](crypto::CryptoModule cryptoModule) {
     identityKeys = cryptoModule.getIdentityKeys();
   };
   NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
   return identityKeys;
 }
 
 crypto::EncryptedData NotificationsCryptoModule::initializeNotificationsSession(
     const std::string &identityKeys,
     const std::string &prekey,
     const std::string &prekeySignature,
     const std::string &oneTimeKeys,
     const std::string &callingProcessName) {
   crypto::EncryptedData initialEncryptedMessage;
   auto caller = [&](crypto::CryptoModule &cryptoModule) {
     cryptoModule.initializeOutboundForSendingSession(
         NotificationsCryptoModule::keyserverHostedNotificationsID,
         std::vector<uint8_t>(identityKeys.begin(), identityKeys.end()),
         std::vector<uint8_t>(prekey.begin(), prekey.end()),
         std::vector<uint8_t>(prekeySignature.begin(), prekeySignature.end()),
         std::vector<uint8_t>(oneTimeKeys.begin(), oneTimeKeys.end()));
     initialEncryptedMessage = cryptoModule.encrypt(
         NotificationsCryptoModule::keyserverHostedNotificationsID,
         NotificationsCryptoModule::initialEncryptedMessageContent);
   };
   NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
   return initialEncryptedMessage;
 }
 
 bool NotificationsCryptoModule::isNotificationsSessionInitialized(
     const std::string &callingProcessName) {
   bool sessionInitialized;
   auto caller = [&sessionInitialized](crypto::CryptoModule &cryptoModule) {
     sessionInitialized = cryptoModule.hasSessionFor(
         NotificationsCryptoModule::keyserverHostedNotificationsID);
   };
   NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
   return sessionInitialized;
 }
 
 void NotificationsCryptoModule::clearSensitiveData() {
   std::string notificationsCryptoAccountPath =
       PlatformSpecificTools::getNotificationsCryptoAccountPath();
   if (remove(notificationsCryptoAccountPath.c_str()) == -1 && errno != ENOENT) {
     throw std::runtime_error(
         "Unable to remove notifications crypto account. Security requirements "
         "might be violated.");
   }
 }
 
 std::string NotificationsCryptoModule::decrypt(
     const std::string &data,
     const size_t messageType,
     const std::string &callingProcessName) {
   std::string decryptedData;
   auto caller = [&](crypto::CryptoModule &cryptoModule) {
     decryptedData = cryptoModule.decrypt(
         NotificationsCryptoModule::keyserverHostedNotificationsID,
         {std::vector<uint8_t>(data.begin(), data.end()), messageType});
   };
   NotificationsCryptoModule::callCryptoModule(caller, callingProcessName);
   return decryptedData;
 }
 } // namespace comm