diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js
--- a/lib/reducers/message-reducer.js
+++ b/lib/reducers/message-reducer.js
@@ -1870,4 +1870,4 @@
   };
 }
 
-export { freshMessageStore, reduceMessageStore };
+export { freshMessageStore, reduceMessageStore, mergeUpdatesWithMessageInfos };
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
@@ -62,24 +62,15 @@
       viewerID,
     );
     resultThreadInfo = newThread;
-    updateInfos.push(
-      {
-        type: updateTypes.JOIN_THREAD,
-        id: uuid.v4(),
-        time,
-        threadInfo: newThread,
-        rawMessageInfos: [addMembersMessage],
-        truncationStatus: messageTruncationStatus.EXHAUSTIVE,
-        rawEntryInfos: [],
-      },
-      {
-        type: updateTypes.UPDATE_THREAD_READ_STATUS,
-        id: uuid.v4(),
-        time,
-        threadID: existingThreadDetails.threadID,
-        unread: true,
-      },
-    );
+    updateInfos.push({
+      type: updateTypes.JOIN_THREAD,
+      id: uuid.v4(),
+      time,
+      threadInfo: newThread,
+      rawMessageInfos: [addMembersMessage],
+      truncationStatus: messageTruncationStatus.EXHAUSTIVE,
+      rawEntryInfos: [],
+    });
     const repliesCountUpdate = createRepliesCountUpdate(newThread, [
       addMembersMessage,
     ]);
@@ -139,13 +130,6 @@
         time,
         threadInfo: newThreadInfo,
       },
-      {
-        type: updateTypes.UPDATE_THREAD_READ_STATUS,
-        id: uuid.v4(),
-        time,
-        threadID: existingThreadDetails.threadID,
-        unread: true,
-      },
     );
     rawMessageInfos.push(addMembersMessage);
   }
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
@@ -140,16 +140,6 @@
         });
       }
 
-      if (rawMessageInfos.length > 0) {
-        updateInfos.push({
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID,
-          unread: true,
-        });
-      }
-
       return {
         rawMessageInfos,
         updateInfos,
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
@@ -48,15 +48,7 @@
     if (userIsMember(currentThreadInfo, joinerID)) {
       return {
         rawMessageInfos: [joinThreadMessage],
-        updateInfos: [
-          {
-            type: updateTypes.UPDATE_THREAD_READ_STATUS,
-            id: uuid.v4(),
-            time,
-            threadID: existingThreadDetails.threadID,
-            unread: true,
-          },
-        ],
+        updateInfos: [],
       };
     }
 
@@ -70,24 +62,15 @@
         },
         viewerID,
       );
-      updateInfos.push(
-        {
-          type: updateTypes.JOIN_THREAD,
-          id: uuid.v4(),
-          time,
-          threadInfo: newThreadInfo,
-          rawMessageInfos: [joinThreadMessage],
-          truncationStatus: messageTruncationStatus.EXHAUSTIVE,
-          rawEntryInfos: [],
-        },
-        {
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID: existingThreadDetails.threadID,
-          unread: true,
-        },
-      );
+      updateInfos.push({
+        type: updateTypes.JOIN_THREAD,
+        id: uuid.v4(),
+        time,
+        threadInfo: newThreadInfo,
+        rawMessageInfos: [joinThreadMessage],
+        truncationStatus: messageTruncationStatus.EXHAUSTIVE,
+        rawEntryInfos: [],
+      });
       const repliesCountUpdate = createRepliesCountUpdate(newThreadInfo, [
         joinThreadMessage,
       ]);
@@ -130,13 +113,6 @@
           time,
           threadInfo: updatedThreadInfo,
         },
-        {
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID: existingThreadDetails.threadID,
-          unread: true,
-        },
       );
     }
     return {
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
@@ -64,13 +64,6 @@
           time,
           threadInfo: updatedThreadInfo,
         },
-        {
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID,
-          unread: true,
-        },
       );
     }
 
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
@@ -1,10 +1,13 @@
 // @flow
 
+import _groupBy from 'lodash/fp/groupBy.js';
 import * as React from 'react';
+import uuid from 'uuid';
 
 import { dmOpSpecs } from './dm-op-specs.js';
 import { useLoggedInUserInfo } from '../../hooks/account-hooks.js';
 import { useGetLatestMessageEdit } from '../../hooks/latest-message-edit.js';
+import { mergeUpdatesWithMessageInfos } from '../../reducers/message-reducer.js';
 import { useDispatchWithMessageSource } from '../../hooks/ops-hooks.js';
 import type { MessageSourceMetadata } from '../../types/db-ops-types.js';
 import {
@@ -12,7 +15,8 @@
   processDMOpsActionType,
   queueDMOpsActionType,
 } from '../../types/dm-ops.js';
-import { useSelector } from '../../utils/redux-utils.js';
+import { updateTypes } from '../../types/update-types-enum.js';
+import { useDispatch, useSelector } from '../../utils/redux-utils.js';
 
 function useProcessDMOperation(): (
   dmOp: DMOperation,
@@ -63,6 +67,32 @@
         dmOp.type
       ].processDMOperation(dmOp, viewerID, utilities);
 
+      const { rawMessageInfos: allNewMessageInfos } =
+        mergeUpdatesWithMessageInfos(rawMessageInfos, updateInfos);
+      const messagesByThreadID = _groupBy(message => message.threadID)(
+        allNewMessageInfos,
+      );
+      for (const threadID in messagesByThreadID) {
+        const messagesFromOtherPeers = messagesByThreadID[threadID].filter(
+          message => message.creatorID !== viewerID,
+        );
+        if (messagesFromOtherPeers.length === 0) {
+          continue;
+        }
+        // We take the most recent timestamp to make sure that updates older
+        // than it won't flip the status to read.
+        const time = Math.max(
+          messagesFromOtherPeers.map(message => message.time),
+        );
+        updateInfos.push({
+          type: updateTypes.UPDATE_THREAD_READ_STATUS,
+          id: uuid.v4(),
+          time,
+          threadID,
+          unread: true,
+        });
+      }
+
       dispatchWithMessageSource(
         {
           type: processDMOpsActionType,
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
@@ -69,13 +69,6 @@
             time,
             threadInfo: updatedThreadInfo,
           },
-          {
-            type: updateTypes.UPDATE_THREAD_READ_STATUS,
-            id: uuid.v4(),
-            time,
-            threadID,
-            unread: true,
-          },
         );
       }
       return {
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
@@ -1,7 +1,5 @@
 // @flow
 
-import uuid from 'uuid';
-
 import type {
   DMOperationSpec,
   ProcessDMOperationUtilities,
@@ -9,7 +7,6 @@
 import { createRepliesCountUpdate } from './dm-op-utils.js';
 import type { DMSendEditMessageOperation } from '../../types/dm-ops.js';
 import { messageTypes } from '../../types/message-types-enum.js';
-import { updateTypes } from '../../types/update-types-enum.js';
 import type { ClientUpdateInfo } from '../../types/update-types.js';
 
 const sendEditMessageSpec: DMOperationSpec<DMSendEditMessageOperation> =
@@ -32,15 +29,6 @@
       };
 
       const updateInfos: Array<ClientUpdateInfo> = [];
-      if (creatorID !== viewerID) {
-        updateInfos.push({
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID,
-          unread: true,
-        });
-      }
       const threadInfo = utilities.threadInfos[threadID];
       const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [
         editMessage,
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
@@ -1,7 +1,5 @@
 // @flow
 
-import uuid from 'uuid';
-
 import type {
   DMOperationSpec,
   ProcessDMOperationUtilities,
@@ -9,7 +7,6 @@
 import { createRepliesCountUpdate } from './dm-op-utils.js';
 import type { DMSendReactionMessageOperation } from '../../types/dm-ops.js';
 import { messageTypes } from '../../types/message-types-enum.js';
-import { updateTypes } from '../../types/update-types-enum.js';
 import type { ClientUpdateInfo } from '../../types/update-types.js';
 
 const sendReactionMessageSpec: DMOperationSpec<DMSendReactionMessageOperation> =
@@ -40,15 +37,6 @@
       };
 
       const updateInfos: Array<ClientUpdateInfo> = [];
-      if (creatorID !== viewerID) {
-        updateInfos.push({
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID,
-          unread: true,
-        });
-      }
       const threadInfo = utilities.threadInfos[threadID];
       const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [
         reactionMessage,
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
@@ -1,7 +1,5 @@
 // @flow
 
-import uuid from 'uuid';
-
 import type {
   DMOperationSpec,
   ProcessDMOperationUtilities,
@@ -9,7 +7,6 @@
 import { createRepliesCountUpdate } from './dm-op-utils.js';
 import type { DMSendTextMessageOperation } from '../../types/dm-ops.js';
 import { messageTypes } from '../../types/message-types-enum.js';
-import { updateTypes } from '../../types/update-types-enum.js';
 import type { ClientUpdateInfo } from '../../types/update-types.js';
 
 const sendTextMessageSpec: DMOperationSpec<DMSendTextMessageOperation> =
@@ -29,15 +26,6 @@
         text,
       };
       const updateInfos: Array<ClientUpdateInfo> = [];
-      if (creatorID !== viewerID) {
-        updateInfos.push({
-          type: updateTypes.UPDATE_THREAD_READ_STATUS,
-          id: uuid.v4(),
-          time,
-          threadID,
-          unread: true,
-        });
-      }
       const threadInfo = utilities.threadInfos[threadID];
       const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [
         textMessage,