diff --git a/desktop/src/main.js b/desktop/src/main.js
--- a/desktop/src/main.js
+++ b/desktop/src/main.js
@@ -306,12 +306,16 @@
 
     const handleEncryptedNotification = (
       encryptedPayload: string,
-      keyserverID: string,
+      senderDeviceDescriptor:
+        | { +keyserverID: string }
+        | { +senderDeviceID: string },
+      type: string,
     ) => {
       if (mainWindow) {
         mainWindow.webContents.send('on-encrypted-notification', {
           encryptedPayload,
-          keyserverID,
+          senderDeviceDescriptor,
+          type,
         });
       }
     };
diff --git a/desktop/src/push-notifications.js b/desktop/src/push-notifications.js
--- a/desktop/src/push-notifications.js
+++ b/desktop/src/push-notifications.js
@@ -131,29 +131,52 @@
   handleClick: (threadID?: string) => void,
   handleEncryptedNotification: (
     encryptedPayload: string,
-    keyserverID: string,
+    senderDeviceDescriptor:
+      | { +keyserverID: string }
+      | { +senderDeviceID: string },
+    type: string,
   ) => void,
 ) {
   if (process.platform === 'darwin') {
     pushNotifications.on('received-apns-notification', (event, userInfo) => {
-      const { keyserverID, encryptedPayload } = userInfo;
+      const { keyserverID, senderDeviceID, encryptedPayload, type } = userInfo;
       if (
         typeof keyserverID === 'string' &&
-        typeof encryptedPayload === 'string'
+        typeof encryptedPayload === 'string' &&
+        typeof type === 'string'
       ) {
-        handleEncryptedNotification(encryptedPayload, keyserverID);
+        handleEncryptedNotification(encryptedPayload, { keyserverID }, type);
+        return;
+      }
+
+      if (
+        typeof senderDeviceID === 'string' &&
+        typeof encryptedPayload === 'string' &&
+        typeof type === 'string'
+      ) {
+        handleEncryptedNotification(encryptedPayload, { senderDeviceID }, type);
         return;
       }
       showNewNotification(userInfo, handleClick);
     });
   } else if (process.platform === 'win32') {
     windowsPushNotifEventEmitter.on('received-wns-notification', payload => {
-      const { keyserverID, encryptedPayload } = payload;
+      const { keyserverID, senderDeviceID, encryptedPayload, type } = payload;
       if (
         typeof keyserverID === 'string' &&
-        typeof encryptedPayload === 'string'
+        typeof encryptedPayload === 'string' &&
+        typeof type === 'string'
+      ) {
+        handleEncryptedNotification(encryptedPayload, { keyserverID }, type);
+        return;
+      }
+
+      if (
+        typeof senderDeviceID === 'string' &&
+        typeof encryptedPayload === 'string' &&
+        typeof type === 'string'
       ) {
-        handleEncryptedNotification(encryptedPayload, keyserverID);
+        handleEncryptedNotification(encryptedPayload, { senderDeviceID }, type);
         return;
       }
       showNewNotification(payload, handleClick);
diff --git a/lib/types/electron-types.js b/lib/types/electron-types.js
--- a/lib/types/electron-types.js
+++ b/lib/types/electron-types.js
@@ -1,5 +1,7 @@
 // @flow
 
+import type { SenderDeviceDescriptor } from './notif-types';
+
 type OnNavigateListener = ({
   +canGoBack: boolean,
   +canGoForward: boolean,
@@ -13,7 +15,8 @@
 
 type OnEncryptedNotificationListener = (data: {
   encryptedPayload: string,
-  keyserverID?: string,
+  type: string,
+  senderDeviceDescriptor: SenderDeviceDescriptor,
 }) => mixed;
 
 export type ElectronBridge = {
diff --git a/web/push-notif/notif-crypto-utils.js b/web/push-notif/notif-crypto-utils.js
--- a/web/push-notif/notif-crypto-utils.js
+++ b/web/push-notif/notif-crypto-utils.js
@@ -14,12 +14,17 @@
 import type {
   PlainTextWebNotification,
   EncryptedWebNotification,
+  SenderDeviceDescriptor,
 } from 'lib/types/notif-types.js';
 import { getCookieIDFromCookie } from 'lib/utils/cookie-utils.js';
 import { getMessageForException } from 'lib/utils/errors.js';
 import { promiseAll } from 'lib/utils/promises.js';
 import { assertWithValidator } from 'lib/utils/validation-utils.js';
 
+import {
+  fetchAuthMetadata,
+  getNotifsInboundKeysForDeviceID,
+} from './services-client.js';
 import {
   type EncryptedData,
   decryptData,
@@ -92,6 +97,16 @@
   return data;
 }
 
+async function deserializeEncryptedDataOptional<T>(
+  encryptedData: ?EncryptedData,
+  encryptionKey: ?CryptoKey,
+): Promise<?T> {
+  if (!encryptedData || !encryptionKey) {
+    return undefined;
+  }
+  return deserializeEncryptedData<T>(encryptedData, encryptionKey);
+}
+
 async function serializeUnencryptedData<T>(
   data: T,
   encryptionKey: CryptoKey,
@@ -116,6 +131,15 @@
   return await importJWKKey(((cryptoKey: any): SubtleCrypto$JsonWebKey));
 }
 
+async function validateCryptoKeyOptional(
+  cryptoKey: ?CryptoKey | ?SubtleCrypto$JsonWebKey,
+): Promise<?CryptoKey> {
+  if (!cryptoKey) {
+    return undefined;
+  }
+  return validateCryptoKey(cryptoKey);
+}
+
 async function getCryptoKeyPersistentForm(
   cryptoKey: CryptoKey,
 ): Promise<CryptoKey | SubtleCrypto$JsonWebKey> {
@@ -128,6 +152,95 @@
   return await exportKeyToJWK(cryptoKey);
 }
 
+async function getNotifsAccountWithOlmData(
+  senderDeviceDescriptor: SenderDeviceDescriptor,
+): Promise<{
+  +encryptedOlmData: ?EncryptedData,
+  +encryptionKey: ?CryptoKey,
+  +olmDataKey: string,
+  +encryptionKeyDBLabel: string,
+  +encryptedOlmAccount: ?EncryptedData,
+  +accountEncryptionKey: ?CryptoKey,
+  +synchronizationValue: ?string,
+}> {
+  let olmDataKey;
+  let olmDataEncryptionKeyDBLabel;
+  const { keyserverID, senderDeviceID } = senderDeviceDescriptor;
+
+  if (keyserverID) {
+    const olmDBKeys = await getNotifsOlmSessionDBKeys(keyserverID);
+    const { olmDataKey: fetchedOlmDataKey, encryptionKeyDBKey } = olmDBKeys;
+    olmDataKey = fetchedOlmDataKey;
+    olmDataEncryptionKeyDBLabel = encryptionKeyDBKey;
+  } else {
+    invariant(
+      senderDeviceID,
+      'keyserverID or SenderDeviceID must be present to decrypt a notif',
+    );
+    olmDataKey = getOlmDataKeyForDeviceID(senderDeviceID);
+    olmDataEncryptionKeyDBLabel =
+      getOlmEncryptionKeyDBLabelForDeviceID(senderDeviceID);
+  }
+
+  const queryResult = await localforage.getMultipleItems<{
+    notificationAccount: ?EncryptedData,
+    notificationAccountEncryptionKey: ?CryptoKey,
+    synchronizationValue: ?number,
+    [string]: ?EncryptedData | ?CryptoKey | ?SubtleCrypto$JsonWebKey,
+  }>(
+    [
+      INDEXED_DB_NOTIFS_ACCOUNT_KEY,
+      INDEXED_DB_NOTIFS_ACCOUNT_ENCRYPTION_KEY_DB_LABEL,
+      olmDataEncryptionKeyDBLabel,
+      olmDataKey,
+    ],
+    INDEXED_DB_NOTIFS_SYNC_KEY,
+  );
+
+  const {
+    values: {
+      notificationAccount,
+      notificationAccountEncryptionKey,
+      [olmDataKey]: maybeEncryptedOlmData,
+      [olmDataEncryptionKeyDBLabel]: maybeOlmDataEncryptionKey,
+    },
+    synchronizationValue,
+  } = queryResult;
+
+  if (!notificationAccount || !notificationAccountEncryptionKey) {
+    throw new Error(
+      'Attempt to decrypt notification but olm account not initialized.',
+    );
+  }
+
+  const encryptedOlmData: ?EncryptedData = maybeEncryptedOlmData
+    ? assertWithValidator(maybeEncryptedOlmData, encryptedAESDataValidator)
+    : undefined;
+
+  const olmDataEncryptionKey: ?CryptoKey | ?SubtleCrypto$JsonWebKey =
+    maybeOlmDataEncryptionKey
+      ? assertWithValidator(
+          maybeOlmDataEncryptionKey,
+          extendedCryptoKeyValidator,
+        )
+      : undefined;
+
+  const [encryptionKey, accountEncryptionKey] = await Promise.all([
+    validateCryptoKeyOptional(olmDataEncryptionKey),
+    validateCryptoKey(notificationAccountEncryptionKey),
+  ]);
+
+  return {
+    encryptedOlmData,
+    encryptionKey,
+    encryptionKeyDBLabel: olmDataEncryptionKeyDBLabel,
+    encryptedOlmAccount: notificationAccount,
+    olmDataKey,
+    accountEncryptionKey,
+    synchronizationValue,
+  };
+}
+
 async function persistNotifsAccountWithOlmData(input: {
   +olmDataKey?: string,
   +olmEncryptionKeyDBLabel?: string,
@@ -223,8 +336,14 @@
 async function decryptWebNotification(
   encryptedNotification: EncryptedWebNotification,
 ): Promise<PlainTextWebNotification | WebNotifDecryptionError> {
-  const { id, keyserverID, encryptedPayload } = encryptedNotification;
-  invariant(keyserverID, 'KeyserverID must be present to decrypt a notif');
+  const {
+    id,
+    encryptedPayload,
+    type: messageType,
+    ...rest
+  } = encryptedNotification;
+  const senderDeviceDescriptor: SenderDeviceDescriptor = rest;
+
   const utilsData = await localforage.getItem<WebNotifsServiceUtilsData>(
     WEB_NOTIFS_SERVICE_UTILS_KEY,
   );
@@ -234,9 +353,11 @@
   }
   const { olmWasmPath, staffCanSee } = (utilsData: WebNotifsServiceUtilsData);
 
-  let olmDBKeys;
+  let notifsAccountWithOlmData;
   try {
-    olmDBKeys = await getNotifsOlmSessionDBKeys(keyserverID);
+    notifsAccountWithOlmData = await getNotifsAccountWithOlmData(
+      senderDeviceDescriptor,
+    );
   } catch (e) {
     return {
       id,
@@ -244,38 +365,109 @@
       displayErrorMessage: staffCanSee,
     };
   }
-  const { olmDataKey, encryptionKeyDBKey } = olmDBKeys;
-  const [encryptedOlmData, encryptionKey] = await Promise.all([
-    localforage.getItem<EncryptedData>(olmDataKey),
-    retrieveEncryptionKey(encryptionKeyDBKey),
-  ]);
 
-  if (!encryptionKey || !encryptedOlmData) {
-    return {
-      id,
-      error: 'Received encrypted notification but olm session was not created',
-      displayErrorMessage: staffCanSee,
-    };
-  }
+  const {
+    encryptionKey,
+    encryptedOlmData,
+    olmDataKey,
+    encryptionKeyDBLabel: olmEncryptionKeyDBLabel,
+    accountEncryptionKey,
+    encryptedOlmAccount,
+    synchronizationValue,
+  } = notifsAccountWithOlmData;
 
   try {
-    await olm.init({ locateFile: () => olmWasmPath });
+    const [notificationsOlmData, accountWithPicklingKey] = await Promise.all([
+      deserializeEncryptedDataOptional<NotificationsOlmDataType>(
+        encryptedOlmData,
+        encryptionKey,
+      ),
+      deserializeEncryptedDataOptional<PickledOLMAccount>(
+        encryptedOlmAccount,
+        accountEncryptionKey,
+      ),
+      olm.init({ locateFile: () => olmWasmPath }),
+    ]);
 
-    const decryptedNotification = await commonDecrypt<PlainTextWebNotification>(
-      encryptedOlmData,
-      olmDataKey,
-      encryptionKey,
-      encryptedPayload,
-    );
+    let decryptedNotification;
+    let updatedOlmData;
+    let updatedNotifsAccount;
 
-    const { unreadCount } = decryptedNotification;
+    const { senderDeviceID, keyserverID } = senderDeviceDescriptor;
 
-    invariant(keyserverID, 'Keyserver ID must be set to update badge counts');
-    await updateNotifsUnreadCountStorage({
-      [keyserverID]: unreadCount,
-    });
+    if (keyserverID) {
+      invariant(
+        notificationsOlmData && encryptionKey,
+        'Received encrypted notification but keyserver olm session was not created',
+      );
+
+      const {
+        decryptedNotification: resultDecryptedNotification,
+        updatedOlmData: resultUpdatedOlmData,
+      } = await commonDecrypt<PlainTextWebNotification>(
+        notificationsOlmData,
+        encryptedPayload,
+      );
+
+      decryptedNotification = resultDecryptedNotification;
+      updatedOlmData = resultUpdatedOlmData;
+      const { unreadCount } = decryptedNotification;
+
+      invariant(keyserverID, 'Keyserver ID must be set to update badge counts');
+      await Promise.all([
+        persistNotifsAccountWithOlmData({
+          olmDataKey,
+          olmData: updatedOlmData,
+          olmEncryptionKeyDBLabel,
+          encryptionKey,
+          forceWrite: false,
+          synchronizationValue,
+        }),
+        updateNotifsUnreadCountStorage({
+          [keyserverID]: unreadCount,
+        }),
+      ]);
+
+      return { id, ...decryptedNotification };
+    } else {
+      invariant(
+        senderDeviceID,
+        'keyserverID or SenderDeviceID must be present to decrypt a notif',
+      );
+      invariant(
+        accountWithPicklingKey,
+        'Received encrypted notification but notifs olm account not created',
+      );
 
-    return { id, ...decryptedNotification };
+      const {
+        decryptedNotification: resultDecryptedNotification,
+        updatedOlmData: resultUpdatedOlmData,
+        updatedNotifsAccount: resultUpdatedNotifsAccount,
+      } = await commonPeerDecrypt<PlainTextWebNotification>(
+        senderDeviceID,
+        notificationsOlmData,
+        accountWithPicklingKey,
+        messageType,
+        encryptedPayload,
+      );
+
+      decryptedNotification = resultDecryptedNotification;
+      updatedOlmData = resultUpdatedOlmData;
+      updatedNotifsAccount = resultUpdatedNotifsAccount;
+
+      await persistNotifsAccountWithOlmData({
+        accountWithPicklingKey: updatedNotifsAccount,
+        accountEncryptionKey,
+        encryptionKey,
+        olmData: updatedOlmData,
+        olmDataKey,
+        olmEncryptionKeyDBLabel,
+        synchronizationValue,
+        forceWrite: false,
+      });
+
+      return { id, ...decryptedNotification };
+    }
   } catch (e) {
     return {
       id,
@@ -287,19 +479,16 @@
 
 async function decryptDesktopNotification(
   encryptedPayload: string,
+  messageType: string,
   staffCanSee: boolean,
-  keyserverID?: string,
+  senderDeviceDescriptor: SenderDeviceDescriptor,
 ): Promise<{ +[string]: mixed }> {
-  let encryptedOlmData, encryptionKey, olmDataKey;
-  try {
-    const { olmDataKey: olmDataKeyValue, encryptionKeyDBKey } =
-      await getNotifsOlmSessionDBKeys(keyserverID);
+  const { keyserverID, senderDeviceID } = senderDeviceDescriptor;
 
-    olmDataKey = olmDataKeyValue;
-
-    [encryptedOlmData, encryptionKey] = await Promise.all([
-      localforage.getItem<EncryptedData>(olmDataKey),
-      retrieveEncryptionKey(encryptionKeyDBKey),
+  let notifsAccountWithOlmData;
+  try {
+    [notifsAccountWithOlmData] = await Promise.all([
+      getNotifsAccountWithOlmData(senderDeviceDescriptor),
       initOlm(),
     ]);
   } catch (e) {
@@ -309,65 +498,126 @@
     };
   }
 
-  if (!encryptionKey || !encryptedOlmData) {
-    return {
-      error: 'Received encrypted notification but olm session was not created',
-      displayErrorMessage: staffCanSee,
-    };
-  }
+  const {
+    encryptionKey,
+    encryptedOlmData,
+    olmDataKey,
+    encryptionKeyDBLabel: olmEncryptionKeyDBLabel,
+    accountEncryptionKey,
+    encryptedOlmAccount,
+    synchronizationValue,
+  } = notifsAccountWithOlmData;
 
-  let decryptedNotification;
   try {
-    decryptedNotification = await commonDecrypt<{ +[string]: mixed }>(
-      encryptedOlmData,
-      olmDataKey,
-      encryptionKey,
-      encryptedPayload,
-    );
+    const [notificationsOlmData, accountWithPicklingKey] = await Promise.all([
+      deserializeEncryptedDataOptional<NotificationsOlmDataType>(
+        encryptedOlmData,
+        encryptionKey,
+      ),
+      deserializeEncryptedDataOptional<PickledOLMAccount>(
+        encryptedOlmAccount,
+        accountEncryptionKey,
+      ),
+    ]);
+
+    if (keyserverID) {
+      invariant(
+        notificationsOlmData && encryptionKey,
+        'Received encrypted notification but keyserver olm session was not created',
+      );
+
+      const { decryptedNotification, updatedOlmData } = await commonDecrypt<{
+        +[string]: mixed,
+      }>(notificationsOlmData, encryptedPayload);
+
+      const updatedOlmDataPersistencePromise = persistNotifsAccountWithOlmData({
+        olmDataKey,
+        olmData: updatedOlmData,
+        olmEncryptionKeyDBLabel,
+        encryptionKey,
+        forceWrite: false,
+        synchronizationValue,
+      });
+
+      // iOS notifications require that unread count is set under
+      // `badge` key. Since MacOS notifications are created by the
+      // same function the unread count is also set under `badge` key
+      const { badge } = decryptedNotification;
+      if (typeof badge === 'number') {
+        await Promise.all([
+          updateNotifsUnreadCountStorage({ [(keyserverID: string)]: badge }),
+          updatedOlmDataPersistencePromise,
+        ]);
+        return decryptedNotification;
+      }
+
+      const { unreadCount } = decryptedNotification;
+      if (typeof unreadCount === 'number') {
+        await Promise.all([
+          updateNotifsUnreadCountStorage({
+            [(keyserverID: string)]: unreadCount,
+          }),
+          updatedOlmDataPersistencePromise,
+        ]);
+      }
+
+      return decryptedNotification;
+    } else {
+      invariant(
+        senderDeviceID,
+        'keyserverID or SenderDeviceID must be present to decrypt a notif',
+      );
+
+      invariant(
+        accountWithPicklingKey,
+        'Received encrypted notification but notifs olm account not created',
+      );
+
+      const { decryptedNotification, updatedOlmData, updatedNotifsAccount } =
+        await commonPeerDecrypt<{
+          +[string]: mixed,
+        }>(
+          senderDeviceID,
+          notificationsOlmData,
+          accountWithPicklingKey,
+          messageType,
+          encryptedPayload,
+        );
+
+      await persistNotifsAccountWithOlmData({
+        accountWithPicklingKey: updatedNotifsAccount,
+        accountEncryptionKey,
+        encryptionKey,
+        olmData: updatedOlmData,
+        olmDataKey,
+        olmEncryptionKeyDBLabel,
+        synchronizationValue,
+        forceWrite: false,
+      });
+
+      return decryptedNotification;
+    }
   } catch (e) {
     return {
       error: e.message,
       staffCanSee,
     };
   }
-
-  if (!keyserverID) {
-    return decryptedNotification;
-  }
-
-  // iOS notifications require that unread count is set under
-  // `badge` key. Since MacOS notifications are created by the
-  // same function the unread count is also set under `badge` key
-  const { badge } = decryptedNotification;
-  if (typeof badge === 'number') {
-    await updateNotifsUnreadCountStorage({ [(keyserverID: string)]: badge });
-    return decryptedNotification;
-  }
-
-  const { unreadCount } = decryptedNotification;
-  if (typeof unreadCount === 'number') {
-    await updateNotifsUnreadCountStorage({
-      [(keyserverID: string)]: unreadCount,
-    });
-  }
-  return decryptedNotification;
 }
 
 async function commonDecrypt<T>(
-  encryptedOlmData: EncryptedData,
-  olmDataKey: string,
-  encryptionKey: CryptoKey,
+  notificationsOlmData: NotificationsOlmDataType,
   encryptedPayload: string,
-): Promise<T> {
-  const serializedOlmData = await decryptData(encryptedOlmData, encryptionKey);
+): Promise<{
+  +decryptedNotification: T,
+  +updatedOlmData: NotificationsOlmDataType,
+}> {
   const {
     mainSession,
     picklingKey,
     pendingSessionUpdate,
     updateCreationTimestamp,
-  }: NotificationsOlmDataType = JSON.parse(
-    new TextDecoder().decode(serializedOlmData),
-  );
+  } = notificationsOlmData;
 
   let updatedOlmData: NotificationsOlmDataType;
   let decryptedNotification: T;
@@ -410,14 +660,134 @@
     };
   }
 
-  const updatedEncryptedSession = await encryptData(
-    new TextEncoder().encode(JSON.stringify(updatedOlmData)),
-    encryptionKey,
+  return { decryptedNotification, updatedOlmData };
+}
+
+async function commonPeerDecrypt<T>(
+  senderDeviceID: string,
+  notificationsOlmData: ?NotificationsOlmDataType,
+  notificationAccount: PickledOLMAccount,
+  messageType: string,
+  encryptedPayload: string,
+): Promise<{
+  +decryptedNotification: T,
+  +updatedOlmData?: NotificationsOlmDataType,
+  +updatedNotifsAccount?: PickledOLMAccount,
+}> {
+  if (
+    messageType !== olmEncryptedMessageTypes.PREKEY.toString() &&
+    messageType !== olmEncryptedMessageTypes.TEXT.toString()
+  ) {
+    throw new Error(
+      `Received message of invalid type from device: ${senderDeviceID}`,
+    );
+  }
+
+  let isSenderChainEmpty = true;
+  let hasReceivedMessage = false;
+  const sessionExists = !!notificationsOlmData;
+
+  if (notificationsOlmData) {
+    const session = new olm.Session();
+    session.unpickle(
+      notificationsOlmData.picklingKey,
+      notificationsOlmData.pendingSessionUpdate,
+    );
+
+    isSenderChainEmpty = session.is_sender_chain_empty();
+    hasReceivedMessage = session.has_received_message();
+  }
+
+  // regular message
+  const isRegularMessage =
+    !!notificationsOlmData &&
+    messageType === olmEncryptedMessageTypes.TEXT.toString();
+
+  const isRegularPrekeyMessage =
+    !!notificationsOlmData &&
+    messageType === olmEncryptedMessageTypes.PREKEY.toString() &&
+    isSenderChainEmpty &&
+    hasReceivedMessage;
+
+  if (!!notificationsOlmData && (isRegularMessage || isRegularPrekeyMessage)) {
+    return await commonDecrypt<T>(notificationsOlmData, encryptedPayload);
+  }
+
+  // At this point we either face race condition or session reset attempt or
+  // session initialization attempt. For each of this scenario new inbound
+  // session must be created in order to decrypt message
+  const authMetadata = await fetchAuthMetadata();
+  const notifInboundKeys = await getNotifsInboundKeysForDeviceID(
+    senderDeviceID,
+    authMetadata,
+  );
+
+  const account = new olm.Account();
+  const session = new olm.Session();
+
+  account.unpickle(
+    notificationAccount.picklingKey,
+    notificationAccount.pickledAccount,
   );
 
-  await localforage.setItem(olmDataKey, updatedEncryptedSession);
+  if (notifInboundKeys.error) {
+    throw new Error(notifInboundKeys.error);
+  }
+
+  invariant(
+    notifInboundKeys.curve25519,
+    'curve25519 must be present in notifs inbound keys',
+  );
+
+  session.create_inbound_from(
+    account,
+    notifInboundKeys.curve25519,
+    encryptedPayload,
+  );
+
+  const decryptedNotification: T = JSON.parse(
+    session.decrypt(Number(messageType), encryptedPayload),
+  );
+
+  // session reset attempt or session initialization - handled the same
+  const sessionResetAttempt =
+    sessionExists && !isSenderChainEmpty && hasReceivedMessage;
+
+  // race condition
+  const raceCondition =
+    sessionExists && !isSenderChainEmpty && !hasReceivedMessage;
+  const { deviceID: ourDeviceID } = authMetadata;
+  invariant(ourDeviceID, 'Session creation attempt but no device id');
+
+  const thisDeviceWinsRaceCondition = ourDeviceID > senderDeviceID;
+
+  if (
+    !sessionExists ||
+    sessionResetAttempt ||
+    (raceCondition && !thisDeviceWinsRaceCondition)
+  ) {
+    const pickledOlmSession = session.pickle(notificationAccount.picklingKey);
+    const updatedOlmData = {
+      mainSession: pickledOlmSession,
+      pendingSessionUpdate: pickledOlmSession,
+      updateCreationTimestamp: Date.now(),
+      picklingKey: notificationAccount.picklingKey,
+    };
+    const updatedNotifsAccount = {
+      pickledAccount: account.pickle(notificationAccount.picklingKey),
+      picklingKey: notificationAccount.picklingKey,
+    };
+    return {
+      decryptedNotification,
+      updatedOlmData,
+      updatedNotifsAccount,
+    };
+  }
 
-  return decryptedNotification;
+  // If there is a race condition but we win device id comparison
+  // we return object that carries decrypted data but won't persist
+  // any session state
+  return { decryptedNotification };
 }
 
 function decryptWithSession<T>(
diff --git a/web/push-notif/push-notifs-handler.js b/web/push-notif/push-notifs-handler.js
--- a/web/push-notif/push-notifs-handler.js
+++ b/web/push-notif/push-notifs-handler.js
@@ -17,6 +17,7 @@
   type RecordAlertActionPayload,
 } from 'lib/types/alert-types.js';
 import { isDesktopPlatform } from 'lib/types/device-types.js';
+import type { SenderDeviceDescriptor } from 'lib/types/notif-types.js';
 import { getConfig } from 'lib/utils/config.js';
 import { convertNonPendingIDToNewSchema } from 'lib/utils/migration-utils.js';
 import { shouldSkipPushPermissionAlert } from 'lib/utils/push-alerts.js';
@@ -84,15 +85,18 @@
     return electron?.onEncryptedNotification?.(
       async ({
         encryptedPayload,
-        keyserverID,
+        senderDeviceDescriptor,
+        type: messageType,
       }: {
         encryptedPayload: string,
-        keyserverID?: string,
+        type: string,
+        senderDeviceDescriptor: SenderDeviceDescriptor,
       }) => {
         const decryptedPayload = await decryptDesktopNotification(
           encryptedPayload,
+          messageType,
           staffCanSee,
-          keyserverID,
+          senderDeviceDescriptor,
         );
         electron?.showDecryptedNotification(decryptedPayload);
       },