diff --git a/lib/push/android-notif-creators.js b/lib/push/android-notif-creators.js
--- a/lib/push/android-notif-creators.js
+++ b/lib/push/android-notif-creators.js
@@ -35,7 +35,7 @@
 export type CommonNativeNotifInputData = $ReadOnly<{
   +senderDeviceDescriptor: SenderDeviceDescriptor,
   +notifTexts: ResolvedNotifTexts,
-  +newRawMessageInfos: RawMessageInfo[],
+  +newRawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
   +threadID: string,
   +collapseKey: ?string,
   +badgeOnly: boolean,
@@ -55,10 +55,10 @@
     platformDetails: tPlatformDetails,
   });
 
-export type AndroidNotifInputData = {
+export type AndroidNotifInputData = $ReadOnly<{
   ...CommonNativeNotifInputData,
   +notifID: string,
-};
+}>;
 
 export const androidNotifInputDataValidator: TInterface<AndroidNotifInputData> =
   tShape<AndroidNotifInputData>({
diff --git a/lib/push/apns-notif-creators.js b/lib/push/apns-notif-creators.js
--- a/lib/push/apns-notif-creators.js
+++ b/lib/push/apns-notif-creators.js
@@ -30,10 +30,10 @@
 
 export const apnMaxNotificationPayloadByteSize = 4096;
 
-export type APNsNotifInputData = {
+export type APNsNotifInputData = $ReadOnly<{
   ...CommonNativeNotifInputData,
   +uniqueID: string,
-};
+}>;
 
 export const apnsNotifInputDataValidator: TInterface<APNsNotifInputData> =
   tShape<APNsNotifInputData>({
@@ -413,13 +413,19 @@
   }));
 }
 
-type APNsBadgeOnlyNotificationInputData = {
+type SenderDescriptorWithPlatformDetails = {
   +senderDeviceDescriptor: SenderDeviceDescriptor,
-  +badge?: number,
-  +threadID?: string,
   +platformDetails: PlatformDetails,
 };
 
+type APNsBadgeOnlyNotificationInputData = $ReadOnly<
+  | {
+      ...SenderDescriptorWithPlatformDetails,
+      +badge: string,
+    }
+  | { ...SenderDescriptorWithPlatformDetails, +threadID: string },
+>;
+
 async function createAPNsBadgeOnlyNotification(
   encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
   inputData: APNsBadgeOnlyNotificationInputData,
diff --git a/lib/push/send-hooks.react.js b/lib/push/send-hooks.react.js
--- a/lib/push/send-hooks.react.js
+++ b/lib/push/send-hooks.react.js
@@ -1,16 +1,19 @@
 // @flow
 
+import invariant from 'invariant';
 import * as React from 'react';
 import uuid from 'uuid';
 
 import {
   preparePushNotifs,
+  prepareOwnDevicesPushNotifs,
   type PerUserTargetedNotifications,
 } from './send-utils.js';
 import { ENSCacheContext } from '../components/ens-cache-provider.react.js';
 import { NeynarClientContext } from '../components/neynar-client-provider.react.js';
 import { usePeerOlmSessionsCreatorContext } from '../components/peer-olm-session-creator-provider.react.js';
 import { thickRawThreadInfosSelector } from '../selectors/thread-selectors.js';
+import { IdentityClientContext } from '../shared/identity-client-context.js';
 import { useTunnelbroker } from '../tunnelbroker/tunnelbroker-context.js';
 import type {
   TargetedAPNsNotification,
@@ -27,7 +30,6 @@
   TunnelbrokerWNSNotif,
 } from '../types/tunnelbroker/notif-types.js';
 import { getConfig } from '../utils/config.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
 import { getMessageForException } from '../utils/errors.js';
 import { useSelector } from '../utils/redux-utils.js';
 
@@ -98,6 +100,9 @@
 function useSendPushNotifs(): (
   notifCreationData: ?NotificationsCreationData,
 ) => Promise<?PerUserTargetedNotifications> {
+  const client = React.useContext(IdentityClientContext);
+  invariant(client, 'Identity context should be set');
+  const { getAuthMetadata } = client;
   const rawMessageInfos = useSelector(state => state.messageStore.messages);
   const thickRawThreadInfos = useSelector(thickRawThreadInfosSelector);
   const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos);
@@ -114,9 +119,17 @@
       if (!notifCreationData) {
         return;
       }
-      const deviceID = await getContentSigningKey();
+      const { deviceID, userID: senderUserID } = await getAuthMetadata();
+      if (!deviceID || !senderUserID) {
+        return;
+      }
+
       const senderDeviceDescriptor = { senderDeviceID: deviceID };
-      const { messageDatas } = notifCreationData;
+      const senderInfo = {
+        senderUserID,
+        senderDeviceDescriptor,
+      };
+      const { messageDatas, rescindData, badgeUpdateData } = notifCreationData;
 
       const pushNotifsPreparationInput = {
         encryptedNotifUtilsAPI,
@@ -131,17 +144,36 @@
         getFCNames,
       };
 
-      const preparedPushNotifs = await preparePushNotifs(
-        pushNotifsPreparationInput,
-      );
+      const ownDevicesPushNotifsPreparationInput = {
+        encryptedNotifUtilsAPI,
+        senderInfo,
+        olmSessionCreator,
+        auxUserInfos,
+        rescindData,
+        badgeUpdateData,
+      };
+
+      const [preparedPushNotifs, preparedOwnDevicesPushNotifs] =
+        await Promise.all([
+          preparePushNotifs(pushNotifsPreparationInput),
+          prepareOwnDevicesPushNotifs(ownDevicesPushNotifsPreparationInput),
+        ]);
 
-      if (!preparedPushNotifs) {
+      if (!preparedPushNotifs && !prepareOwnDevicesPushNotifs) {
         return;
       }
 
+      let allPreparedPushNotifs = preparedPushNotifs;
+      if (preparedOwnDevicesPushNotifs && senderUserID) {
+        allPreparedPushNotifs = {
+          ...allPreparedPushNotifs,
+          [senderUserID]: preparedOwnDevicesPushNotifs,
+        };
+      }
+
       const sendPromises = [];
-      for (const userID in preparedPushNotifs) {
-        for (const notif of preparedPushNotifs[userID]) {
+      for (const userID in allPreparedPushNotifs) {
+        for (const notif of allPreparedPushNotifs[userID]) {
           if (notif.targetedNotification.notification.encryptionFailed) {
             continue;
           }
@@ -186,6 +218,7 @@
       await Promise.all(sendPromises);
     },
     [
+      getAuthMetadata,
       sendNotif,
       encryptedNotifUtilsAPI,
       olmSessionCreator,
diff --git a/lib/push/send-utils.js b/lib/push/send-utils.js
--- a/lib/push/send-utils.js
+++ b/lib/push/send-utils.js
@@ -3,8 +3,16 @@
 import _pickBy from 'lodash/fp/pickBy.js';
 import uuidv4 from 'uuid/v4.js';
 
-import { createAndroidVisualNotification } from './android-notif-creators.js';
-import { createAPNsVisualNotification } from './apns-notif-creators.js';
+import {
+  createAndroidVisualNotification,
+  createAndroidBadgeOnlyNotification,
+  createAndroidNotificationRescind,
+} from './android-notif-creators.js';
+import {
+  createAPNsVisualNotification,
+  createAPNsBadgeOnlyNotification,
+  createAPNsNotificationRescind,
+} from './apns-notif-creators.js';
 import {
   stringToVersionKey,
   getDevicesByPlatform,
@@ -103,12 +111,12 @@
   messageInfos: { +[id: string]: RawMessageInfo },
   thickRawThreadInfos: ThickRawThreadInfos,
   auxUserInfos: AuxUserInfos,
-  messageDatas: $ReadOnlyArray<MessageData>,
+  messageDatas: ?$ReadOnlyArray<MessageData>,
 ): Promise<{
   +pushInfos: ?PushInfo,
   +rescindInfos: ?PushInfo,
 }> {
-  if (messageDatas.length === 0) {
+  if (!messageDatas || messageDatas.length === 0) {
     return { pushInfos: null, rescindInfos: null };
   }
 
@@ -250,6 +258,48 @@
   };
 }
 
+type SenderInfo = {
+  +senderUserID: string,
+  +senderDeviceDescriptor: SenderDeviceDescriptor,
+};
+
+type OwnDevicesPushInfo = {
+  +devices: $ReadOnlyArray<Device>,
+};
+
+function getOwnDevicesPushInfo(
+  senderInfo: SenderInfo,
+  auxUserInfos: AuxUserInfos,
+): ?OwnDevicesPushInfo {
+  const {
+    senderUserID,
+    senderDeviceDescriptor: { senderDeviceID },
+  } = senderInfo;
+
+  if (!senderDeviceID) {
+    return null;
+  }
+
+  const senderDevicesWithPlatformDetails =
+    auxUserInfos[senderUserID].devicesPlatformDetails;
+
+  if (!senderDevicesWithPlatformDetails) {
+    return null;
+  }
+
+  const devices = Object.entries(senderDevicesWithPlatformDetails)
+    .filter(([deviceID]) => deviceID !== senderDeviceID)
+    .map(([deviceID, identityPlatformDetails]) => ({
+      platformDetails: identityPlatformDetailsToPlatformDetails(
+        identityPlatformDetails,
+      ),
+      deliveryID: deviceID,
+      cryptoID: deviceID,
+    }));
+
+  return { devices };
+}
+
 function pushInfoToCollapsableNotifInfo(pushInfo: PushInfo): {
   +usersToCollapseKeysToInfo: {
     [string]: { [string]: CollapsableNotifInfo },
@@ -393,6 +443,96 @@
 
   return { notifTexts, newRawMessageInfos, badgeOnly };
 }
+type BuildNotifsForPlatformInput<
+  PlatformType: Platform,
+  NotifCreatorinputBase,
+  TargetedNotificationType,
+  NotifCreatorInput: { +platformDetails: PlatformDetails, ... },
+> = {
+  +platform: PlatformType,
+  +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  +notifCreatorCallback: (
+    encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+    input: NotifCreatorInput,
+    devices: $ReadOnlyArray<NotificationTargetDevice>,
+  ) => Promise<$ReadOnlyArray<TargetedNotificationType>>,
+  +notifCreatorInputBase: NotifCreatorinputBase,
+  +transformInputBase: (
+    inputBase: NotifCreatorinputBase,
+    platformDetails: PlatformDetails,
+  ) => NotifCreatorInput,
+  +versionToDevices: $ReadOnlyMap<
+    string,
+    $ReadOnlyArray<NotificationTargetDevice>,
+  >,
+};
+
+async function buildNotifsForPlatform<
+  PlatformType: Platform,
+  NotifCreatorinputBase,
+  TargetedNotificationType,
+  NotifCreatorInput: { +platformDetails: PlatformDetails, ... },
+>(
+  input: BuildNotifsForPlatformInput<
+    PlatformType,
+    NotifCreatorinputBase,
+    TargetedNotificationType,
+    NotifCreatorInput,
+  >,
+): Promise<
+  $ReadOnlyArray<{
+    +platform: PlatformType,
+    +targetedNotification: TargetedNotificationType,
+  }>,
+> {
+  const {
+    encryptedNotifUtilsAPI,
+    versionToDevices,
+    notifCreatorCallback,
+    notifCreatorInputBase,
+    platform,
+    transformInputBase,
+  } = input;
+
+  const promises: Array<
+    Promise<
+      $ReadOnlyArray<{
+        +platform: PlatformType,
+        +targetedNotification: TargetedNotificationType,
+      }>,
+    >,
+  > = [];
+
+  for (const [versionKey, devices] of versionToDevices) {
+    const { codeVersion, stateVersion, majorDesktopVersion } =
+      stringToVersionKey(versionKey);
+
+    const platformDetails = {
+      platform,
+      codeVersion,
+      stateVersion,
+      majorDesktopVersion,
+    };
+
+    const inputData = transformInputBase(
+      notifCreatorInputBase,
+      platformDetails,
+    );
+
+    promises.push(
+      (async () => {
+        return (
+          await notifCreatorCallback(encryptedNotifUtilsAPI, inputData, devices)
+        ).map(targetedNotification => ({
+          platform,
+          targetedNotification,
+        }));
+      })(),
+    );
+  }
+
+  return (await Promise.all(promises)).flat();
+}
 
 type BuildNotifsForUserDevicesInputData = {
   +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
@@ -450,196 +590,263 @@
 
   const iosVersionToDevices = devicesByPlatform.get('ios');
   if (iosVersionToDevices) {
-    for (const [versionKey, devices] of iosVersionToDevices) {
-      const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
-      const platformDetails = {
+    promises.push(
+      buildNotifsForPlatform({
         platform: 'ios',
-        codeVersion,
-        stateVersion,
-      };
-      const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
-        newRawMessageInfos,
-        platformDetails,
-      );
-
-      promises.push(
-        (async () => {
-          return (
-            await createAPNsVisualNotification(
-              encryptedNotifUtilsAPI,
-              {
-                senderDeviceDescriptor,
-                notifTexts,
-                newRawMessageInfos: shimmedNewRawMessageInfos,
-                threadID,
-                collapseKey: undefined,
-                badgeOnly,
-                unreadCount: undefined,
-                platformDetails,
-                uniqueID: uuidv4(),
-              },
-              devices,
-            )
-          ).map(targetedNotification => ({
-            platform: 'ios',
-            targetedNotification,
-          }));
-        })(),
-      );
-    }
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAPNsVisualNotification,
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          newRawMessageInfos: shimUnsupportedRawMessageInfos(
+            newRawMessageInfos,
+            platformDetails,
+          ),
+          platformDetails,
+        }),
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          notifTexts,
+          threadID,
+          collapseKey: undefined,
+          badgeOnly,
+          uniqueID: uuidv4(),
+        },
+        versionToDevices: iosVersionToDevices,
+      }),
+    );
   }
 
   const androidVersionToDevices = devicesByPlatform.get('android');
   if (androidVersionToDevices) {
-    for (const [versionKey, devices] of androidVersionToDevices) {
-      const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
-      const platformDetails = {
+    promises.push(
+      buildNotifsForPlatform({
         platform: 'android',
-        codeVersion,
-        stateVersion,
-      };
-      const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
-        newRawMessageInfos,
-        platformDetails,
-      );
-
-      promises.push(
-        (async () => {
-          return (
-            await createAndroidVisualNotification(
-              encryptedNotifUtilsAPI,
-              {
-                senderDeviceDescriptor,
-                notifTexts,
-                newRawMessageInfos: shimmedNewRawMessageInfos,
-                threadID,
-                collapseKey: undefined,
-                badgeOnly,
-                unreadCount: undefined,
-                platformDetails,
-                notifID: uuidv4(),
-              },
-              devices,
-            )
-          ).map(targetedNotification => ({
-            platform: 'android',
-            targetedNotification,
-          }));
-        })(),
-      );
-    }
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAndroidVisualNotification,
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          newRawMessageInfos: shimUnsupportedRawMessageInfos(
+            newRawMessageInfos,
+            platformDetails,
+          ),
+          platformDetails,
+        }),
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          notifTexts,
+          threadID,
+          collapseKey: undefined,
+          badgeOnly,
+          notifID: uuidv4(),
+        },
+        versionToDevices: androidVersionToDevices,
+      }),
+    );
   }
 
   const macosVersionToDevices = devicesByPlatform.get('macos');
   if (macosVersionToDevices) {
-    for (const [versionKey, devices] of macosVersionToDevices) {
-      const { codeVersion, stateVersion, majorDesktopVersion } =
-        stringToVersionKey(versionKey);
-      const platformDetails = {
+    promises.push(
+      buildNotifsForPlatform({
         platform: 'macos',
-        codeVersion,
-        stateVersion,
-        majorDesktopVersion,
-      };
-      const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
-        newRawMessageInfos,
-        platformDetails,
-      );
-
-      promises.push(
-        (async () => {
-          return (
-            await createAPNsVisualNotification(
-              encryptedNotifUtilsAPI,
-              {
-                senderDeviceDescriptor,
-                notifTexts,
-                newRawMessageInfos: shimmedNewRawMessageInfos,
-                threadID,
-                collapseKey: undefined,
-                badgeOnly,
-                unreadCount: undefined,
-                platformDetails,
-                uniqueID: uuidv4(),
-              },
-              devices,
-            )
-          ).map(targetedNotification => ({
-            platform: 'macos',
-            targetedNotification,
-          }));
-        })(),
-      );
-    }
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAPNsVisualNotification,
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          newRawMessageInfos: shimUnsupportedRawMessageInfos(
+            newRawMessageInfos,
+            platformDetails,
+          ),
+          platformDetails,
+        }),
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          notifTexts,
+          threadID,
+          collapseKey: undefined,
+          badgeOnly,
+          uniqueID: uuidv4(),
+        },
+        versionToDevices: macosVersionToDevices,
+      }),
+    );
   }
 
   const windowsVersionToDevices = devicesByPlatform.get('windows');
   if (windowsVersionToDevices) {
-    for (const [versionKey, devices] of windowsVersionToDevices) {
-      const { codeVersion, stateVersion, majorDesktopVersion } =
-        stringToVersionKey(versionKey);
-      const platformDetails = {
+    promises.push(
+      buildNotifsForPlatform({
         platform: 'windows',
-        codeVersion,
-        stateVersion,
-        majorDesktopVersion,
-      };
-
-      promises.push(
-        (async () => {
-          return (
-            await createWNSNotification(
-              encryptedNotifUtilsAPI,
-              {
-                notifTexts,
-                threadID,
-                senderDeviceDescriptor,
-                platformDetails,
-              },
-              devices,
-            )
-          ).map(targetedNotification => ({
-            platform: 'windows',
-            targetedNotification,
-          }));
-        })(),
-      );
-    }
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createWNSNotification,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          notifTexts,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: windowsVersionToDevices,
+      }),
+    );
   }
 
   const webVersionToDevices = devicesByPlatform.get('web');
   if (webVersionToDevices) {
-    for (const [versionKey, devices] of webVersionToDevices) {
-      const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
-      const platformDetails = {
+    promises.push(
+      buildNotifsForPlatform({
         platform: 'web',
-        codeVersion,
-        stateVersion,
-      };
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createWebNotification,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          notifTexts,
+          threadID,
+          id: uuidv4(),
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: webVersionToDevices,
+      }),
+    );
+  }
 
-      promises.push(
-        (async () => {
-          return (
-            await createWebNotification(
-              encryptedNotifUtilsAPI,
-              {
-                notifTexts,
-                threadID,
-                senderDeviceDescriptor,
-                platformDetails,
-                id: uuidv4(),
-              },
-              devices,
-            )
-          ).map(targetedNotification => ({
-            platform: 'web',
-            targetedNotification,
-          }));
-        })(),
-      );
-    }
+  return (await Promise.all(promises)).flat();
+}
+
+async function buildRescindsForOwnDevices(
+  encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  senderDeviceDescriptor: SenderDeviceDescriptor,
+  devicesByPlatform: $ReadOnlyMap<
+    Platform,
+    $ReadOnlyMap<string, $ReadOnlyArray<NotificationTargetDevice>>,
+  >,
+  rescindData: { +threadID: string },
+): Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+  const { threadID } = rescindData;
+  const promises: Array<
+    Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>>,
+  > = [];
+
+  const iosVersionToDevices = devicesByPlatform.get('ios');
+  if (iosVersionToDevices) {
+    promises.push(
+      buildNotifsForPlatform({
+        platform: 'ios',
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAPNsNotificationRescind,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: iosVersionToDevices,
+      }),
+    );
   }
 
+  const androidVersionToDevices = devicesByPlatform.get('android');
+  if (androidVersionToDevices) {
+    promises.push(
+      buildNotifsForPlatform({
+        platform: 'android',
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAndroidNotificationRescind,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: androidVersionToDevices,
+      }),
+    );
+  }
+  return (await Promise.all(promises)).flat();
+}
+
+async function buildBadgeUpdatesForOwnDevices(
+  encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  senderDeviceDescriptor: SenderDeviceDescriptor,
+  devicesByPlatform: $ReadOnlyMap<
+    Platform,
+    $ReadOnlyMap<string, $ReadOnlyArray<NotificationTargetDevice>>,
+  >,
+  badgeUpdateData: { +threadID: string },
+): Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+  const { threadID } = badgeUpdateData;
+  const promises: Array<
+    Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>>,
+  > = [];
+
+  const iosVersionToDevices = devicesByPlatform.get('ios');
+  if (iosVersionToDevices) {
+    promises.push(
+      buildNotifsForPlatform({
+        platform: 'ios',
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAPNsBadgeOnlyNotification,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: iosVersionToDevices,
+      }),
+    );
+  }
+
+  const androidVersionToDevices = devicesByPlatform.get('android');
+  if (androidVersionToDevices) {
+    promises.push(
+      buildNotifsForPlatform({
+        platform: 'android',
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAndroidBadgeOnlyNotification,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: androidVersionToDevices,
+      }),
+    );
+  }
+
+  const macosVersionToDevices = devicesByPlatform.get('macos');
+  if (macosVersionToDevices) {
+    promises.push(
+      buildNotifsForPlatform({
+        platform: 'macos',
+        encryptedNotifUtilsAPI,
+        notifCreatorCallback: createAPNsBadgeOnlyNotification,
+        notifCreatorInputBase: {
+          senderDeviceDescriptor,
+          threadID,
+        },
+        transformInputBase: (inputBase, platformDetails) => ({
+          ...inputBase,
+          platformDetails,
+        }),
+        versionToDevices: macosVersionToDevices,
+      }),
+    );
+  }
   return (await Promise.all(promises)).flat();
 }
 
@@ -741,6 +948,43 @@
   return promiseAll(perUserBuildNotifsResultPromises);
 }
 
+async function createOlmSessionWithDevices(
+  deviceIDsToUserIDs: {
+    +[string]: string,
+  },
+  olmSessionCreator: (userID: string, deviceID: string) => Promise<void>,
+): Promise<void> {
+  const {
+    initializeCryptoAccount,
+    isNotificationsSessionInitializedWithDevices,
+  } = getConfig().olmAPI;
+  await initializeCryptoAccount();
+
+  const deviceIDsToSessionPresence =
+    await isNotificationsSessionInitializedWithDevices(
+      Object.keys(deviceIDsToUserIDs),
+    );
+
+  const olmSessionCreationPromises = [];
+  for (const deviceID in deviceIDsToSessionPresence) {
+    if (deviceIDsToSessionPresence[deviceID]) {
+      continue;
+    }
+    olmSessionCreationPromises.push(
+      olmSessionCreator(deviceIDsToUserIDs[deviceID], deviceID),
+    );
+  }
+
+  try {
+    await Promise.allSettled(olmSessionCreationPromises);
+  } catch (e) {
+    // session creation may fail for some devices
+    // but we should still pursue notification
+    // delivery for others
+    console.log(e);
+  }
+}
+
 type PreparePushNotifsInputData = {
   +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
   +senderDeviceDescriptor: SenderDeviceDescriptor,
@@ -748,7 +992,7 @@
   +messageInfos: { +[id: string]: RawMessageInfo },
   +thickRawThreadInfos: ThickRawThreadInfos,
   +auxUserInfos: AuxUserInfos,
-  +messageDatas: $ReadOnlyArray<MessageData>,
+  +messageDatas: ?$ReadOnlyArray<MessageData>,
   +userInfos: UserInfos,
   +getENSNames: ?GetENSNames,
   +getFCNames: ?GetFCNames,
@@ -781,12 +1025,6 @@
     return null;
   }
 
-  const {
-    initializeCryptoAccount,
-    isNotificationsSessionInitializedWithDevices,
-  } = getConfig().olmAPI;
-  await initializeCryptoAccount();
-
   const deviceIDsToUserIDs: { [string]: string } = {};
   for (const userID in pushInfos) {
     for (const device of pushInfos[userID].devices) {
@@ -794,29 +1032,7 @@
     }
   }
 
-  const deviceIDsToSessionPresence =
-    await isNotificationsSessionInitializedWithDevices(
-      Object.keys(deviceIDsToUserIDs),
-    );
-
-  const olmSessionCreationPromises = [];
-  for (const deviceID in deviceIDsToSessionPresence) {
-    if (deviceIDsToSessionPresence[deviceID]) {
-      continue;
-    }
-    olmSessionCreationPromises.push(
-      olmSessionCreator(deviceIDsToUserIDs[deviceID], deviceID),
-    );
-  }
-
-  try {
-    await Promise.allSettled(olmSessionCreationPromises);
-  } catch (e) {
-    // session creation may fail for some devices
-    // but we should still pursue notification
-    // delivery for others
-    console.log(e);
-  }
+  await createOlmSessionWithDevices(deviceIDsToUserIDs, olmSessionCreator);
 
   return await buildNotifsFromPushInfo({
     encryptedNotifUtilsAPI,
@@ -829,8 +1045,65 @@
   });
 }
 
+type PrepareOwnDevicesPushNotifsInputData = {
+  +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  +senderInfo: SenderInfo,
+  +olmSessionCreator: (userID: string, deviceID: string) => Promise<void>,
+  +auxUserInfos: AuxUserInfos,
+  +rescindData?: { threadID: string },
+  +badgeUpdateData?: { threadID: string },
+};
+
+async function prepareOwnDevicesPushNotifs(
+  inputData: PrepareOwnDevicesPushNotifsInputData,
+): Promise<?$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+  const {
+    encryptedNotifUtilsAPI,
+    senderInfo,
+    olmSessionCreator,
+    auxUserInfos,
+    rescindData,
+    badgeUpdateData,
+  } = inputData;
+
+  const ownDevicesPushInfo = getOwnDevicesPushInfo(senderInfo, auxUserInfos);
+
+  if (!ownDevicesPushInfo) {
+    return null;
+  }
+
+  const { senderUserID, senderDeviceDescriptor } = senderInfo;
+  const deviceIDsToUserIDs: { [string]: string } = {};
+
+  for (const device of ownDevicesPushInfo.devices) {
+    deviceIDsToUserIDs[device.cryptoID] = senderUserID;
+  }
+
+  await createOlmSessionWithDevices(deviceIDsToUserIDs, olmSessionCreator);
+  const devicesByPlatform = getDevicesByPlatform(ownDevicesPushInfo.devices);
+
+  if (rescindData) {
+    return await buildRescindsForOwnDevices(
+      encryptedNotifUtilsAPI,
+      senderDeviceDescriptor,
+      devicesByPlatform,
+      rescindData,
+    );
+  } else if (badgeUpdateData) {
+    return await buildBadgeUpdatesForOwnDevices(
+      encryptedNotifUtilsAPI,
+      senderDeviceDescriptor,
+      devicesByPlatform,
+      badgeUpdateData,
+    );
+  } else {
+    return null;
+  }
+}
+
 export {
   preparePushNotifs,
+  prepareOwnDevicesPushNotifs,
   generateNotifUserInfoPromise,
   pushInfoToCollapsableNotifInfo,
   mergeUserToCollapsableInfo,
diff --git a/lib/shared/dm-ops/change-thread-read-status-spec.js b/lib/shared/dm-ops/change-thread-read-status-spec.js
--- a/lib/shared/dm-ops/change-thread-read-status-spec.js
+++ b/lib/shared/dm-ops/change-thread-read-status-spec.js
@@ -11,6 +11,15 @@
 
 const changeThreadReadStatusSpec: DMOperationSpec<DMChangeThreadReadStatusOperation> =
   Object.freeze({
+    notificationsCreationData: async (
+      dmOperation: DMChangeThreadReadStatusOperation,
+    ) => {
+      const { threadID, unread } = dmOperation;
+      if (unread) {
+        return { badgeUpdateData: { threadID } };
+      }
+      return { rescindData: { threadID } };
+    },
     processDMOperation: async (
       dmOperation: DMChangeThreadReadStatusOperation,
     ) => {
diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js
--- a/lib/types/notif-types.js
+++ b/lib/types/notif-types.js
@@ -28,9 +28,14 @@
     prefix: t.maybe(t.String),
   });
 
-export type NotificationsCreationData = {
-  +messageDatas: $ReadOnlyArray<MessageData>,
-};
+export type NotificationsCreationData =
+  | {
+      +messageDatas: $ReadOnlyArray<MessageData>,
+    }
+  | {
+      +rescindData: { threadID: string },
+    }
+  | { +badgeUpdateData: { threadID: string } };
 
 export type SenderDeviceDescriptor =
   | { +keyserverID: string }