diff --git a/lib/shared/dm-ops/add-members-spec.js b/lib/shared/dm-ops/add-members-spec.js
--- a/lib/shared/dm-ops/add-members-spec.js
+++ b/lib/shared/dm-ops/add-members-spec.js
@@ -80,13 +80,6 @@
 }
 
 const addMembersSpec: DMOperationSpec<DMAddMembersOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMAddMembersOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createAddNewMembersMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (
     dmOperation: DMAddMembersOperation,
     utilities: ProcessDMOperationUtilities,
@@ -94,8 +87,10 @@
     const { editorID, time, addedUserIDs, threadID } = dmOperation;
     const { viewerID, threadInfos } = utilities;
 
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createAddNewMembersMessageDataWithInfoFromDMOperation(dmOperation);
+
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const rawMessageInfos = [rawMessageInfo];
 
     const currentThreadInfo = threadInfos[threadID];
@@ -156,10 +151,15 @@
       },
     ];
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     return {
       rawMessageInfos,
       updateInfos,
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/add-viewer-to-thread-members-spec.js b/lib/shared/dm-ops/add-viewer-to-thread-members-spec.js
--- a/lib/shared/dm-ops/add-viewer-to-thread-members-spec.js
+++ b/lib/shared/dm-ops/add-viewer-to-thread-members-spec.js
@@ -47,17 +47,6 @@
 
 const addViewerToThreadMembersSpec: DMOperationSpec<DMAddViewerToThreadMembersOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMAddViewerToThreadMembersOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createAddViewerToThreadMembersMessageDataWithInfoFromDMOp(
-            dmOperation,
-          ),
-        ],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMAddViewerToThreadMembersOperation,
       utilities: ProcessDMOperationUtilities,
@@ -66,8 +55,9 @@
         dmOperation;
       const { threadInfos } = utilities;
 
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createAddViewerToThreadMembersMessageDataWithInfoFromDMOp(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = messageID ? [rawMessageInfo] : [];
 
       const threadID = existingThreadDetails.threadID;
@@ -99,6 +89,10 @@
         }
       }
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       if (currentThreadInfo) {
         const { membershipPermissions, roleID } =
           createPermissionsForNewMembers(currentThreadInfo, utilities);
@@ -144,6 +138,7 @@
           rawMessageInfos,
           updateInfos,
           blobOps: [],
+          notificationsCreationData,
         };
       }
 
@@ -182,6 +177,7 @@
         rawMessageInfos: [],
         updateInfos,
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
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
@@ -12,29 +12,34 @@
 } from '../../types/dm-ops.js';
 import { updateTypes } from '../../types/update-types-enum.js';
 
+function generateNotificationsCreationData(
+  dmOperation: DMChangeThreadReadStatusOperation,
+) {
+  const { threadID, unread } = dmOperation;
+  if (unread) {
+    return { badgeUpdateData: { threadID } };
+  }
+  return { rescindData: { threadID } };
+}
+
 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,
       utilities: ProcessDMOperationUtilities,
     ) => {
       const { threadID, unread, time } = dmOperation;
 
+      const notificationsCreationData =
+        generateNotificationsCreationData(dmOperation);
+
       const threadInfo = utilities.threadInfos[threadID];
       if (threadInfo.timestamps.currentUser.unread > time) {
         return {
           rawMessageInfos: [],
           updateInfos: [],
           blobOps: [],
+          notificationsCreationData,
         };
       }
 
@@ -51,6 +56,7 @@
         rawMessageInfos: [],
         updateInfos,
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/change-thread-settings-spec.js b/lib/shared/dm-ops/change-thread-settings-spec.js
--- a/lib/shared/dm-ops/change-thread-settings-spec.js
+++ b/lib/shared/dm-ops/change-thread-settings-spec.js
@@ -135,14 +135,6 @@
 
 const changeThreadSettingsSpec: DMOperationSpec<DMChangeThreadSettingsOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMChangeThreadSettingsOperation,
-    ) => {
-      const { fieldNameToMessageData } =
-        createChangeSettingsMessageDatasAndUpdate(dmOperation);
-
-      return { messageDatasWithMessageInfos: values(fieldNameToMessageData) };
-    },
     processDMOperation: async (
       dmOperation: DMChangeThreadSettingsOperation,
       utilities: ProcessDMOperationUtilities,
@@ -187,10 +179,15 @@
         });
       }
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: values(fieldNameToMessageData),
+      };
+
       return {
         rawMessageInfos,
         updateInfos,
         blobOps,
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/change-thread-subscription.js b/lib/shared/dm-ops/change-thread-subscription.js
--- a/lib/shared/dm-ops/change-thread-subscription.js
+++ b/lib/shared/dm-ops/change-thread-subscription.js
@@ -30,6 +30,9 @@
           updateInfos: [],
           rawMessageInfos: [],
           blobOps: [],
+          notificationsCreationData: {
+            messageDatasWithMessageInfos: [],
+          },
         };
       }
 
@@ -82,6 +85,9 @@
         updateInfos,
         rawMessageInfos: [],
         blobOps: [],
+        notificationsCreationData: {
+          messageDatasWithMessageInfos: [],
+        },
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/create-entry-spec.js b/lib/shared/dm-ops/create-entry-spec.js
--- a/lib/shared/dm-ops/create-entry-spec.js
+++ b/lib/shared/dm-ops/create-entry-spec.js
@@ -36,18 +36,12 @@
 }
 
 const createEntrySpec: DMOperationSpec<DMCreateEntryOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMCreateEntryOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (dmOperation: DMCreateEntryOperation) => {
     const { threadID, creatorID, time, entryID, entryDate, text } = dmOperation;
 
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createMessageDataWithInfoFromDMOperation(dmOperation);
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const rawMessageInfos = [rawMessageInfo];
 
     const date = dateFromString(entryDate);
@@ -72,10 +66,15 @@
       time,
     };
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     return {
       rawMessageInfos,
       updateInfos: [entryUpdateInfo],
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/create-sidebar-spec.js b/lib/shared/dm-ops/create-sidebar-spec.js
--- a/lib/shared/dm-ops/create-sidebar-spec.js
+++ b/lib/shared/dm-ops/create-sidebar-spec.js
@@ -97,32 +97,6 @@
 
 const createSidebarSpec: DMOperationSpec<DMCreateSidebarOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMCreateSidebarOperation,
-      utilities: ProcessDMOperationUtilities,
-    ) => {
-      const {
-        sidebarSourceMessageData,
-        createSidebarMessageData,
-        createSidebarMessageInfo,
-        sidebarSourceMessageInfo,
-      } = await createMessageDatasWithInfosFromDMOperation(
-        dmOperation,
-        utilities,
-      );
-      return {
-        messageDatasWithMessageInfos: [
-          {
-            messageData: sidebarSourceMessageData,
-            rawMessageInfo: sidebarSourceMessageInfo,
-          },
-          {
-            messageData: createSidebarMessageData,
-            rawMessageInfo: createSidebarMessageInfo,
-          },
-        ],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMCreateSidebarOperation,
       utilities: ProcessDMOperationUtilities,
@@ -159,12 +133,16 @@
         utilities,
       );
 
-      const { sidebarSourceMessageInfo, createSidebarMessageInfo } =
-        await createMessageDatasWithInfosFromDMOperation(
-          dmOperation,
-          utilities,
-          rawThreadInfo.color,
-        );
+      const {
+        sidebarSourceMessageData,
+        createSidebarMessageData,
+        createSidebarMessageInfo,
+        sidebarSourceMessageInfo,
+      } = await createMessageDatasWithInfosFromDMOperation(
+        dmOperation,
+        utilities,
+        rawThreadInfo.color,
+      );
 
       const rawMessageInfos: Array<RawMessageInfo> = [
         sidebarSourceMessageInfo,
@@ -181,10 +159,24 @@
         rawEntryInfos: [],
       };
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [
+          {
+            messageData: sidebarSourceMessageData,
+            rawMessageInfo: sidebarSourceMessageInfo,
+          },
+          {
+            messageData: createSidebarMessageData,
+            rawMessageInfo: createSidebarMessageInfo,
+          },
+        ],
+      };
+
       return {
         rawMessageInfos: [], // included in updateInfos below
         updateInfos: [threadJoinUpdateInfo],
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/create-thread-spec.js b/lib/shared/dm-ops/create-thread-spec.js
--- a/lib/shared/dm-ops/create-thread-spec.js
+++ b/lib/shared/dm-ops/create-thread-spec.js
@@ -232,13 +232,6 @@
 
 const createThreadSpec: DMOperationSpec<DMCreateThreadOperation> =
   Object.freeze({
-    notificationsCreationData: async (dmOperation: DMCreateThreadOperation) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMCreateThreadOperation,
       utilities: ProcessDMOperationUtilities,
@@ -265,8 +258,9 @@
         utilities,
       );
 
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
 
       const threadJoinUpdateInfo = {
@@ -279,10 +273,15 @@
         rawEntryInfos: [],
       };
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos: [], // included in updateInfos below
         updateInfos: [threadJoinUpdateInfo],
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/delete-entry-spec.js b/lib/shared/dm-ops/delete-entry-spec.js
--- a/lib/shared/dm-ops/delete-entry-spec.js
+++ b/lib/shared/dm-ops/delete-entry-spec.js
@@ -36,13 +36,6 @@
 }
 
 const deleteEntrySpec: DMOperationSpec<DMDeleteEntryOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMDeleteEntryOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (
     dmOperation: DMDeleteEntryOperation,
     utilities: ProcessDMOperationUtilities,
@@ -58,18 +51,24 @@
     } = dmOperation;
 
     const rawEntryInfo = utilities.entryInfos[entryID];
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createMessageDataWithInfoFromDMOperation(dmOperation);
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const rawMessageInfos = [rawMessageInfo];
 
     invariant(rawEntryInfo?.thick, 'Entry thread should be thick');
     const timestamp = rawEntryInfo.lastUpdatedTime;
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     if (timestamp > time) {
       return {
         rawMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     }
 
@@ -99,6 +98,7 @@
       rawMessageInfos,
       updateInfos: [entryUpdateInfo],
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/dm-op-spec.js b/lib/shared/dm-ops/dm-op-spec.js
--- a/lib/shared/dm-ops/dm-op-spec.js
+++ b/lib/shared/dm-ops/dm-op-spec.js
@@ -6,12 +6,10 @@
 import type { RawEntryInfos } from '../../types/entry-types.js';
 import type { UserIdentitiesResponse } from '../../types/identity-service-types.js';
 import type { RawMessageInfo } from '../../types/message-types.js';
-import type { NotificationsCreationData } from '../../types/notif-types.js';
 import type { ThickRawThreadInfos } from '../../types/thread-types.js';
 
 export type ProcessDMOperationUtilities = {
   +viewerID: string,
-  // Needed to fetch sidebar source messages
   +fetchMessage: (messageID: string) => Promise<?RawMessageInfo>,
   +threadInfos: ThickRawThreadInfos,
   +entryInfos: RawEntryInfos,
@@ -33,10 +31,6 @@
     };
 
 export type DMOperationSpec<DMOp: DMOperation> = {
-  +notificationsCreationData?: (
-    dmOp: DMOp,
-    utilities: ProcessDMOperationUtilities,
-  ) => Promise<NotificationsCreationData>,
   +processDMOperation: (
     dmOp: DMOp,
     utilities: ProcessDMOperationUtilities,
diff --git a/lib/shared/dm-ops/edit-entry-spec.js b/lib/shared/dm-ops/edit-entry-spec.js
--- a/lib/shared/dm-ops/edit-entry-spec.js
+++ b/lib/shared/dm-ops/edit-entry-spec.js
@@ -36,13 +36,6 @@
 }
 
 const editEntrySpec: DMOperationSpec<DMEditEntryOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMEditEntryOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (
     dmOperation: DMEditEntryOperation,
     utilities: ProcessDMOperationUtilities,
@@ -59,18 +52,24 @@
 
     const rawEntryInfo = utilities.entryInfos[entryID];
 
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createMessageDataWithInfoFromDMOperation(dmOperation);
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const rawMessageInfos = [rawMessageInfo];
 
     invariant(rawEntryInfo?.thick, 'Entry should be thick');
     const timestamp = rawEntryInfo.lastUpdatedTime;
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     if (timestamp > time) {
       return {
         rawMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     }
 
@@ -100,6 +99,7 @@
       rawMessageInfos,
       updateInfos: [entryUpdateInfo],
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/join-thread-spec.js b/lib/shared/dm-ops/join-thread-spec.js
--- a/lib/shared/dm-ops/join-thread-spec.js
+++ b/lib/shared/dm-ops/join-thread-spec.js
@@ -44,13 +44,6 @@
 }
 
 const joinThreadSpec: DMOperationSpec<DMJoinThreadOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMJoinThreadOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (
     dmOperation: DMJoinThreadOperation,
     utilities: ProcessDMOperationUtilities,
@@ -59,8 +52,9 @@
     const { viewerID, threadInfos } = utilities;
     const currentThreadInfo = threadInfos[existingThreadDetails.threadID];
 
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createMessageDataWithInfoFromDMOperation(dmOperation);
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const joinThreadMessageInfos = [rawMessageInfo];
 
     const memberTimestamps = { ...currentThreadInfo?.timestamps?.members };
@@ -71,11 +65,16 @@
       };
     }
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     if (memberTimestamps[joinerID].isMember > time) {
       return {
         rawMessageInfos: joinThreadMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     }
 
@@ -176,6 +175,7 @@
       rawMessageInfos,
       updateInfos,
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/leave-thread-spec.js b/lib/shared/dm-ops/leave-thread-spec.js
--- a/lib/shared/dm-ops/leave-thread-spec.js
+++ b/lib/shared/dm-ops/leave-thread-spec.js
@@ -108,13 +108,6 @@
 }
 
 const leaveThreadSpec: DMOperationSpec<DMLeaveThreadOperation> = Object.freeze({
-  notificationsCreationData: async (dmOperation: DMLeaveThreadOperation) => {
-    return {
-      messageDatasWithMessageInfos: [
-        createMessageDataWithInfoFromDMOperation(dmOperation),
-      ],
-    };
-  },
   processDMOperation: async (
     dmOperation: DMLeaveThreadOperation,
     utilities: ProcessDMOperationUtilities,
@@ -123,8 +116,9 @@
     const { viewerID, threadInfos } = utilities;
     const threadInfo = threadInfos[threadID];
 
-    const { rawMessageInfo } =
+    const messageDataWithMessageInfos =
       createMessageDataWithInfoFromDMOperation(dmOperation);
+    const { rawMessageInfo } = messageDataWithMessageInfos;
     const rawMessageInfos = [rawMessageInfo];
 
     const memberTimestamps = { ...threadInfo.timestamps.members };
@@ -139,12 +133,17 @@
       isMember: time,
     };
 
+    const notificationsCreationData = {
+      messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+    };
+
     if (viewerID === editorID) {
       if (threadInfo.timestamps.members[editorID]?.isMember > time) {
         return {
           rawMessageInfos,
           updateInfos: [],
           blobOps: [],
+          notificationsCreationData,
         };
       }
 
@@ -165,6 +164,7 @@
             ),
           ],
           blobOps: [],
+          notificationsCreationData,
         };
       }
 
@@ -213,6 +213,7 @@
           },
         ],
         blobOps: [],
+        notificationsCreationData,
       };
     }
 
@@ -230,6 +231,7 @@
         rawMessageInfos,
         updateInfos,
         blobOps: [],
+        notificationsCreationData,
       };
     }
 
@@ -252,6 +254,7 @@
       rawMessageInfos,
       updateInfos,
       blobOps: [],
+      notificationsCreationData,
     };
   },
   canBeProcessed: async (
diff --git a/lib/shared/dm-ops/process-dm-ops.js b/lib/shared/dm-ops/process-dm-ops.js
--- a/lib/shared/dm-ops/process-dm-ops.js
+++ b/lib/shared/dm-ops/process-dm-ops.js
@@ -26,7 +26,6 @@
   queueDMOpsActionType,
   dmOperationValidator,
 } from '../../types/dm-ops.js';
-import type { NotificationsCreationData } from '../../types/notif-types.js';
 import type { DispatchMetadata } from '../../types/redux-types.js';
 import type { OutboundP2PMessage } from '../../types/sqlite-types.js';
 import { extractUserIDsFromPayload } from '../../utils/conversion-utils.js';
@@ -106,9 +105,9 @@
           dmOperationSpecificationTypes.OUTBOUND &&
         dmOperationSpecification.sendOnly
       ) {
-        const notificationsCreationData = await dmOpSpecs[
+        const { notificationsCreationData } = await dmOpSpecs[
           dmOp.type
-        ].notificationsCreationData?.(dmOp, utilities);
+        ].processDMOperation(dmOp, utilities);
 
         dispatchWithMetadata(
           {
@@ -208,26 +207,17 @@
         });
       }
 
-      const dmOpSpec = dmOpSpecs[dmOp.type];
-      const notificationsCreationDataPromise: Promise<?NotificationsCreationData> =
-        (async () => {
-          if (
-            dmOperationSpecification.type ===
-              dmOperationSpecificationTypes.INBOUND ||
-            !dmOpSpec.notificationsCreationData
-          ) {
-            return null;
-          }
-          return await dmOpSpec.notificationsCreationData(dmOp, utilities);
-        })();
-
-      const [
-        { rawMessageInfos, updateInfos, blobOps },
+      const {
+        rawMessageInfos,
+        updateInfos,
+        blobOps,
         notificationsCreationData,
-      ] = await Promise.all([
-        dmOpSpec.processDMOperation(dmOp, utilities),
-        notificationsCreationDataPromise,
-      ]);
+      } = await dmOpSpecs[dmOp.type].processDMOperation(dmOp, utilities);
+
+      const outboundNotificationsCreationData =
+        dmOperationSpecification.type === dmOperationSpecificationTypes.OUTBOUND
+          ? notificationsCreationData
+          : null;
 
       const holderOps = blobOps
         .map(({ dmOpType, ...holderOp }) => {
@@ -254,7 +244,7 @@
             updateInfos,
             outboundP2PMessages,
             composableMessageID,
-            notificationsCreationData,
+            notificationsCreationData: outboundNotificationsCreationData,
           },
         },
         dispatchMetadata,
@@ -345,21 +335,8 @@
         recipients,
       );
 
-      const spec = dmOpSpecs[op.type];
-
-      const notificationsCreationDataPromise: Promise<?NotificationsCreationData> =
-        (async () => {
-          if (!spec?.notificationsCreationData) {
-            return null;
-          }
-          return await spec.notificationsCreationData(op, utilities);
-        })();
-
-      const [{ rawMessageInfos, updateInfos }, notificationsCreationData] =
-        await Promise.all([
-          dmOpSpecs[op.type].processDMOperation(op, utilities),
-          notificationsCreationDataPromise,
-        ]);
+      const { rawMessageInfos, updateInfos, notificationsCreationData } =
+        await dmOpSpecs[op.type].processDMOperation(op, utilities);
 
       dispatchWithMetadata(
         {
diff --git a/lib/shared/dm-ops/remove-members-spec.js b/lib/shared/dm-ops/remove-members-spec.js
--- a/lib/shared/dm-ops/remove-members-spec.js
+++ b/lib/shared/dm-ops/remove-members-spec.js
@@ -33,15 +33,6 @@
 
 const removeMembersSpec: DMOperationSpec<DMRemoveMembersOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMRemoveMembersOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMRemoveMembersOperation,
       utilities: ProcessDMOperationUtilities,
@@ -50,8 +41,9 @@
       const { viewerID, threadInfos } = utilities;
       const threadInfo = threadInfos[threadID];
 
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
 
       const memberTimestamps = { ...threadInfo.timestamps.members };
@@ -108,10 +100,16 @@
           threadInfo: updatedThreadInfo,
         });
       }
+
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos,
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/send-edit-message-spec.js b/lib/shared/dm-ops/send-edit-message-spec.js
--- a/lib/shared/dm-ops/send-edit-message-spec.js
+++ b/lib/shared/dm-ops/send-edit-message-spec.js
@@ -30,24 +30,21 @@
 
 const sendEditMessageSpec: DMOperationSpec<DMSendEditMessageOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMSendEditMessageOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (dmOperation: DMSendEditMessageOperation) => {
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/send-multimedia-message-spec.js b/lib/shared/dm-ops/send-multimedia-message-spec.js
--- a/lib/shared/dm-ops/send-multimedia-message-spec.js
+++ b/lib/shared/dm-ops/send-multimedia-message-spec.js
@@ -63,27 +63,25 @@
 
 const sendMultimediaMessageSpec: DMOperationSpec<DMSendMultimediaMessageOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMSendMultimediaMessageOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMSendMultimediaMessageOperation,
     ) => {
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
       const updateInfos: Array<ClientUpdateInfo> = [];
       const blobOps = getBlobOpsFromOperation(dmOperation);
+
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos,
         blobOps,
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/send-reaction-message-spec.js b/lib/shared/dm-ops/send-reaction-message-spec.js
--- a/lib/shared/dm-ops/send-reaction-message-spec.js
+++ b/lib/shared/dm-ops/send-reaction-message-spec.js
@@ -38,24 +38,21 @@
 
 const sendReactionMessageSpec: DMOperationSpec<DMSendReactionMessageOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMSendReactionMessageOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (dmOperation: DMSendReactionMessageOperation) => {
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
 
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/send-text-message-spec.js b/lib/shared/dm-ops/send-text-message-spec.js
--- a/lib/shared/dm-ops/send-text-message-spec.js
+++ b/lib/shared/dm-ops/send-text-message-spec.js
@@ -29,24 +29,22 @@
 
 const sendTextMessageSpec: DMOperationSpec<DMSendTextMessageOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMSendTextMessageOperation,
-    ) => {
-      return {
-        messageDatasWithMessageInfos: [
-          createMessageDataWithInfoFromDMOperation(dmOperation),
-        ],
-      };
-    },
     processDMOperation: async (dmOperation: DMSendTextMessageOperation) => {
-      const { rawMessageInfo } =
+      const messageDataWithMessageInfos =
         createMessageDataWithInfoFromDMOperation(dmOperation);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
       const updateInfos: Array<ClientUpdateInfo> = [];
+
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos,
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/shared/dm-ops/update-relationship-spec.js b/lib/shared/dm-ops/update-relationship-spec.js
--- a/lib/shared/dm-ops/update-relationship-spec.js
+++ b/lib/shared/dm-ops/update-relationship-spec.js
@@ -62,33 +62,24 @@
 
 const updateRelationshipSpec: DMOperationSpec<DMUpdateRelationshipOperation> =
   Object.freeze({
-    notificationsCreationData: async (
-      dmOperation: DMUpdateRelationshipOperation,
-      utilities: ProcessDMOperationUtilities,
-    ) => {
-      const messageDataWithMessageInfo =
-        await createMessageDataWithInfoFromDMOperation(
-          dmOperation,
-
-          utilities,
-        );
-      return {
-        messageDatasWithMessageInfos: [messageDataWithMessageInfo],
-      };
-    },
     processDMOperation: async (
       dmOperation: DMUpdateRelationshipOperation,
       utilities: ProcessDMOperationUtilities,
     ) => {
-      const { rawMessageInfo } = await createMessageDataWithInfoFromDMOperation(
-        dmOperation,
-        utilities,
-      );
+      const messageDataWithMessageInfos =
+        await createMessageDataWithInfoFromDMOperation(dmOperation, utilities);
+      const { rawMessageInfo } = messageDataWithMessageInfos;
       const rawMessageInfos = [rawMessageInfo];
+
+      const notificationsCreationData = {
+        messageDatasWithMessageInfos: [messageDataWithMessageInfos],
+      };
+
       return {
         rawMessageInfos,
         updateInfos: [],
         blobOps: [],
+        notificationsCreationData,
       };
     },
     canBeProcessed: async (
diff --git a/lib/types/dm-ops.js b/lib/types/dm-ops.js
--- a/lib/types/dm-ops.js
+++ b/lib/types/dm-ops.js
@@ -521,6 +521,7 @@
   rawMessageInfos: Array<RawMessageInfo>,
   updateInfos: Array<ClientUpdateInfo>,
   blobOps: Array<DMBlobOperation>,
+  notificationsCreationData: NotificationsCreationData,
 };
 
 export const processDMOpsActionType = 'PROCESS_DM_OPS';