diff --git a/lib/ops/thread-store-ops.js b/lib/ops/thread-store-ops.js
--- a/lib/ops/thread-store-ops.js
+++ b/lib/ops/thread-store-ops.js
@@ -1,10 +1,10 @@
 // @flow
 
 import { type BaseStoreOpsHandlers } from './base-ops.js';
+import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
 import type {
   ClientDBThreadInfo,
-  RawThreadInfo,
-  RawThreadInfos,
+  MinimallyEncodedRawThreadInfos,
   ThreadStore,
 } from '../types/thread-types.js';
 import {
@@ -23,7 +23,7 @@
 
 export type ReplaceThreadOperation = {
   +type: 'replace',
-  +payload: { +id: string, +threadInfo: RawThreadInfo },
+  +payload: { +id: string, +threadInfo: MinimallyEncodedRawThreadInfo },
 };
 
 export type ThreadStoreOperation =
@@ -45,7 +45,7 @@
   ThreadStore,
   ThreadStoreOperation,
   ClientDBThreadStoreOperation,
-  RawThreadInfos,
+  MinimallyEncodedRawThreadInfos,
   ClientDBThreadInfo,
 > = {
   processStoreOperations(
@@ -87,7 +87,7 @@
   },
 
   translateClientDBData(data: $ReadOnlyArray<ClientDBThreadInfo>): {
-    +[id: string]: RawThreadInfo,
+    +[id: string]: MinimallyEncodedRawThreadInfo,
   } {
     return Object.fromEntries(
       data.map((dbThreadInfo: ClientDBThreadInfo) => [
diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js
--- a/lib/reducers/thread-reducer.js
+++ b/lib/reducers/thread-reducer.js
@@ -1,5 +1,7 @@
 // @flow
 
+import invariant from 'invariant';
+
 import {
   setThreadUnreadStatusActionTypes,
   updateActivityActionTypes,
@@ -32,6 +34,7 @@
 } from '../ops/thread-store-ops.js';
 import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js';
 import { updateSpecs } from '../shared/updates/update-specs.js';
+import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
 import type { BaseAction } from '../types/redux-types.js';
 import { type ClientThreadInconsistencyReportCreationRequest } from '../types/report-types.js';
 import {
@@ -43,8 +46,7 @@
   incrementalStateSyncActionType,
 } from '../types/socket-types.js';
 import type {
-  RawThreadInfo,
-  RawThreadInfos,
+  MinimallyEncodedRawThreadInfos,
   ThreadStore,
 } from '../types/thread-types.js';
 import {
@@ -56,7 +58,7 @@
   threadStoreOpsHandlers;
 
 function generateOpsForThreadUpdates(
-  threadInfos: RawThreadInfos,
+  threadInfos: MinimallyEncodedRawThreadInfos,
   payload: {
     +updatesResult: { +newUpdates: $ReadOnlyArray<ClientUpdateInfo>, ... },
     ...
@@ -92,10 +94,16 @@
       {
         type: 'remove_all',
       },
-      ...Object.keys(newThreadInfos).map((id: string) => ({
-        type: 'replace',
-        payload: { id, threadInfo: newThreadInfos[id] },
-      })),
+      ...Object.keys(newThreadInfos).map((id: string) => {
+        invariant(
+          newThreadInfos[id].minimallyEncoded,
+          'newThreadInfos must be minimallyEncoded for current clients',
+        );
+        return {
+          type: 'replace',
+          payload: { id, threadInfo: newThreadInfos[id] },
+        };
+      }),
     ];
     const updatedThreadStore = processThreadStoreOperations(
       state,
@@ -170,60 +178,31 @@
   } else if (action.type === updateSubscriptionActionTypes.success) {
     const { threadID, subscription } = action.payload;
     const threadInfo = state.threadInfos[threadID];
-    // TODO (atul): Try to get rid of this ridiculous branching.
-    if (threadInfo.minimallyEncoded) {
-      const newThreadInfo = {
-        ...threadInfo,
-        currentUser: {
-          ...threadInfo.currentUser,
-          subscription,
-        },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: newThreadInfo,
-          },
-        },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    } else {
-      const newThreadInfo = {
-        ...threadInfo,
-        currentUser: {
-          ...threadInfo.currentUser,
-          subscription,
-        },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: newThreadInfo,
-          },
+    const newThreadInfo = {
+      ...threadInfo,
+      currentUser: {
+        ...threadInfo.currentUser,
+        subscription,
+      },
+    };
+    const threadStoreOperations = [
+      {
+        type: 'replace',
+        payload: {
+          id: threadID,
+          threadInfo: newThreadInfo,
         },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    }
+      },
+    ];
+    const updatedThreadStore = processThreadStoreOperations(
+      state,
+      threadStoreOperations,
+    );
+    return {
+      threadStore: updatedThreadStore,
+      newThreadInconsistencies: [],
+      threadStoreOperations,
+    };
   } else if (action.type === saveMessagesActionType) {
     const threadIDToMostRecentTime = new Map<string, number>();
     for (const messageInfo of action.payload.rawMessageInfos) {
@@ -232,7 +211,7 @@
         threadIDToMostRecentTime.set(messageInfo.threadID, messageInfo.time);
       }
     }
-    const changedThreadInfos: { [string]: RawThreadInfo } = {};
+    const changedThreadInfos: { [string]: MinimallyEncodedRawThreadInfo } = {};
     for (const [threadID, mostRecentTime] of threadIDToMostRecentTime) {
       const threadInfo = state.threadInfos[threadID];
       if (
@@ -242,25 +221,13 @@
       ) {
         continue;
       }
-      const changedThreadInfo = state.threadInfos[threadID];
-      // TODO (atul): Try to get rid of this ridiculous branching.
-      if (changedThreadInfo.minimallyEncoded) {
-        changedThreadInfos[threadID] = {
-          ...changedThreadInfo,
-          currentUser: {
-            ...changedThreadInfo.currentUser,
-            unread: true,
-          },
-        };
-      } else {
-        changedThreadInfos[threadID] = {
-          ...changedThreadInfo,
-          currentUser: {
-            ...changedThreadInfo.currentUser,
-            unread: true,
-          },
-        };
-      }
+      changedThreadInfos[threadID] = {
+        ...threadInfo,
+        currentUser: {
+          ...threadInfo.currentUser,
+          unread: true,
+        },
+      };
     }
     if (Object.keys(changedThreadInfos).length !== 0) {
       const threadStoreOperations = Object.keys(changedThreadInfos).map(id => ({
@@ -303,6 +270,10 @@
     const threadStoreOperations: ThreadStoreOperation[] = [];
     if (rawThreadInfos) {
       for (const rawThreadInfo of rawThreadInfos) {
+        invariant(
+          rawThreadInfo.minimallyEncoded,
+          'rawThreadInfo must be minimallyEncoded for current clients',
+        );
         threadStoreOperations.push({
           type: 'replace',
           payload: {
@@ -339,33 +310,19 @@
       threadStoreOperations,
     };
   } else if (action.type === updateActivityActionTypes.success) {
-    const updatedThreadInfos: { [string]: RawThreadInfo } = {};
+    const updatedThreadInfos: { [string]: MinimallyEncodedRawThreadInfo } = {};
     for (const setToUnread of action.payload.result.unfocusedToUnread) {
       const threadInfo = state.threadInfos[setToUnread];
-      // TODO (atul): Try to get rid of this ridiculous branching.
-      if (threadInfo.minimallyEncoded) {
-        if (threadInfo && !threadInfo.currentUser.unread) {
-          updatedThreadInfos[setToUnread] = {
-            ...threadInfo,
-            currentUser: {
-              ...threadInfo.currentUser,
-              unread: true,
-            },
-          };
-        }
-      } else {
-        if (threadInfo && !threadInfo.currentUser.unread) {
-          updatedThreadInfos[setToUnread] = {
-            ...threadInfo,
-            currentUser: {
-              ...threadInfo.currentUser,
-              unread: true,
-            },
-          };
-        }
+      if (threadInfo && !threadInfo.currentUser.unread) {
+        updatedThreadInfos[setToUnread] = {
+          ...threadInfo,
+          currentUser: {
+            ...threadInfo.currentUser,
+            unread: true,
+          },
+        };
       }
     }
-
     if (Object.keys(updatedThreadInfos).length === 0) {
       return {
         threadStore: state,
@@ -392,63 +349,35 @@
   } else if (action.type === setThreadUnreadStatusActionTypes.started) {
     const { threadID, unread } = action.payload;
     const threadInfo = state.threadInfos[threadID];
-    // TODO (atul): Try to get rid of this ridiculous branching.
-    if (threadInfo.minimallyEncoded) {
-      const updatedThreadInfo = {
-        ...threadInfo,
-        currentUser: {
-          ...threadInfo.currentUser,
-          unread,
-        },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: updatedThreadInfo,
-          },
-        },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    } else {
-      const updatedThreadInfo = {
-        ...threadInfo,
-        currentUser: {
-          ...threadInfo.currentUser,
-          unread,
-        },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: updatedThreadInfo,
-          },
+    const updatedThreadInfo = {
+      ...threadInfo,
+      currentUser: {
+        ...threadInfo.currentUser,
+        unread,
+      },
+    };
+    const threadStoreOperations = [
+      {
+        type: 'replace',
+        payload: {
+          id: threadID,
+          threadInfo: updatedThreadInfo,
         },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    }
+      },
+    ];
+    const updatedThreadStore = processThreadStoreOperations(
+      state,
+      threadStoreOperations,
+    );
+    return {
+      threadStore: updatedThreadStore,
+      newThreadInconsistencies: [],
+      threadStoreOperations,
+    };
   } else if (action.type === setThreadUnreadStatusActionTypes.success) {
     const { threadID, resetToUnread } = action.payload;
-    const currentUser = state.threadInfos[threadID].currentUser;
+    const threadInfo = state.threadInfos[threadID];
+    const { currentUser } = threadInfo;
 
     if (!resetToUnread || currentUser.unread) {
       return {
@@ -458,55 +387,28 @@
       };
     }
 
-    const threadInfo = state.threadInfos[threadID];
-    // TODO (atul): Try to get rid of this ridiculous branching.
-    if (threadInfo.minimallyEncoded) {
-      const updatedThread = {
-        ...threadInfo,
-        currentUser: { ...threadInfo.currentUser, unread: true },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: updatedThread,
-          },
-        },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    } else {
-      const updatedThread = {
-        ...threadInfo,
-        currentUser: { ...threadInfo.currentUser, unread: true },
-      };
-      const threadStoreOperations = [
-        {
-          type: 'replace',
-          payload: {
-            id: threadID,
-            threadInfo: updatedThread,
-          },
+    const updatedThread = {
+      ...threadInfo,
+      currentUser: { ...currentUser, unread: true },
+    };
+    const threadStoreOperations = [
+      {
+        type: 'replace',
+        payload: {
+          id: threadID,
+          threadInfo: updatedThread,
         },
-      ];
-      const updatedThreadStore = processThreadStoreOperations(
-        state,
-        threadStoreOperations,
-      );
-      return {
-        threadStore: updatedThreadStore,
-        newThreadInconsistencies: [],
-        threadStoreOperations,
-      };
-    }
+      },
+    ];
+    const updatedThreadStore = processThreadStoreOperations(
+      state,
+      threadStoreOperations,
+    );
+    return {
+      threadStore: updatedThreadStore,
+      newThreadInconsistencies: [],
+      threadStoreOperations,
+    };
   } else if (action.type === setClientDBStoreActionType) {
     return {
       threadStore: action.payload.threadStore ?? state,
diff --git a/lib/shared/updates/delete-account-spec.js b/lib/shared/updates/delete-account-spec.js
--- a/lib/shared/updates/delete-account-spec.js
+++ b/lib/shared/updates/delete-account-spec.js
@@ -3,7 +3,7 @@
 import t from 'tcomb';
 
 import type { UpdateSpec } from './update-spec.js';
-import type { RawThreadInfos } from '../../types/thread-types.js';
+import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js';
 import { updateTypes } from '../../types/update-types-enum.js';
 import type {
   AccountDeletionRawUpdateInfo,
@@ -19,47 +19,27 @@
   AccountDeletionUpdateData,
 > = Object.freeze({
   generateOpsForThreadUpdates(
-    storeThreadInfos: RawThreadInfos,
+    storeThreadInfos: MinimallyEncodedRawThreadInfos,
     update: AccountDeletionUpdateInfo,
   ) {
     const operations = [];
     for (const threadID in storeThreadInfos) {
       const threadInfo = storeThreadInfos[threadID];
-      // TODO (atul): Try to get rid of this ridiculous branching.
-      if (threadInfo.minimallyEncoded) {
-        const newMembers = threadInfo.members.filter(
-          member => member.id !== update.deletedUserID,
-        );
-        if (newMembers.length < threadInfo.members.length) {
-          const updatedThread = {
-            ...threadInfo,
-            members: newMembers,
-          };
-          operations.push({
-            type: 'replace',
-            payload: {
-              id: threadID,
-              threadInfo: updatedThread,
-            },
-          });
-        }
-      } else {
-        const newMembers = threadInfo.members.filter(
-          member => member.id !== update.deletedUserID,
-        );
-        if (newMembers.length < threadInfo.members.length) {
-          const updatedThread = {
-            ...threadInfo,
-            members: newMembers,
-          };
-          operations.push({
-            type: 'replace',
-            payload: {
-              id: threadID,
-              threadInfo: updatedThread,
-            },
-          });
-        }
+      const newMembers = threadInfo.members.filter(
+        member => member.id !== update.deletedUserID,
+      );
+      if (newMembers.length < threadInfo.members.length) {
+        const updatedThread = {
+          ...threadInfo,
+          members: newMembers,
+        };
+        operations.push({
+          type: 'replace',
+          payload: {
+            id: threadID,
+            threadInfo: updatedThread,
+          },
+        });
       }
     }
     return operations;
diff --git a/lib/shared/updates/join-thread-spec.js b/lib/shared/updates/join-thread-spec.js
--- a/lib/shared/updates/join-thread-spec.js
+++ b/lib/shared/updates/join-thread-spec.js
@@ -18,7 +18,7 @@
   messageTruncationStatusValidator,
   rawMessageInfoValidator,
 } from '../../types/message-types.js';
-import { type RawThreadInfos } from '../../types/thread-types.js';
+import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js';
 import { updateTypes } from '../../types/update-types-enum.js';
 import type {
   ThreadJoinUpdateInfo,
@@ -35,12 +35,16 @@
   ThreadJoinUpdateData,
 > = Object.freeze({
   generateOpsForThreadUpdates(
-    storeThreadInfos: RawThreadInfos,
+    storeThreadInfos: MinimallyEncodedRawThreadInfos,
     update: ThreadJoinUpdateInfo,
   ) {
     if (_isEqual(storeThreadInfos[update.threadInfo.id])(update.threadInfo)) {
       return null;
     }
+    invariant(
+      update.threadInfo.minimallyEncoded,
+      'update threadInfo must be minimallyEncoded',
+    );
     return [
       {
         type: 'replace',
diff --git a/lib/shared/updates/update-spec.js b/lib/shared/updates/update-spec.js
--- a/lib/shared/updates/update-spec.js
+++ b/lib/shared/updates/update-spec.js
@@ -14,7 +14,10 @@
   MessageTruncationStatuses,
   FetchMessageInfosResult,
 } from '../../types/message-types.js';
-import type { RawThreadInfos } from '../../types/thread-types.js';
+import type {
+  MinimallyEncodedRawThreadInfos,
+  RawThreadInfos,
+} from '../../types/thread-types.js';
 import type { UpdateType } from '../../types/update-types-enum.js';
 import type {
   ClientUpdateInfo,
@@ -54,7 +57,7 @@
   Data: UpdateData,
 > = {
   +generateOpsForThreadUpdates?: (
-    storeThreadInfos: RawThreadInfos,
+    storeThreadInfos: MinimallyEncodedRawThreadInfos,
     update: UpdateInfo,
   ) => ?$ReadOnlyArray<ThreadStoreOperation>,
   +mergeEntryInfos?: (
diff --git a/lib/shared/updates/update-thread-read-status-spec.js b/lib/shared/updates/update-thread-read-status-spec.js
--- a/lib/shared/updates/update-thread-read-status-spec.js
+++ b/lib/shared/updates/update-thread-read-status-spec.js
@@ -3,7 +3,7 @@
 import t from 'tcomb';
 
 import type { UpdateSpec } from './update-spec.js';
-import type { RawThreadInfos } from '../../types/thread-types.js';
+import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js';
 import { updateTypes } from '../../types/update-types-enum.js';
 import type {
   ThreadReadStatusUpdateInfo,
@@ -18,7 +18,7 @@
   ThreadReadStatusUpdateData,
 > = Object.freeze({
   generateOpsForThreadUpdates(
-    storeThreadInfos: RawThreadInfos,
+    storeThreadInfos: MinimallyEncodedRawThreadInfos,
     update: ThreadReadStatusUpdateInfo,
   ) {
     if (
diff --git a/lib/shared/updates/update-thread-spec.js b/lib/shared/updates/update-thread-spec.js
--- a/lib/shared/updates/update-thread-spec.js
+++ b/lib/shared/updates/update-thread-spec.js
@@ -1,11 +1,12 @@
 // @flow
 
+import invariant from 'invariant';
 import _isEqual from 'lodash/fp/isEqual.js';
 import t from 'tcomb';
 
 import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js';
 import { rawThreadInfoValidator } from '../../permissions/minimally-encoded-thread-permissions-validators.js';
-import { type RawThreadInfos } from '../../types/thread-types.js';
+import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js';
 import { updateTypes } from '../../types/update-types-enum.js';
 import type {
   ThreadUpdateInfo,
@@ -21,12 +22,16 @@
   ThreadUpdateData,
 > = Object.freeze({
   generateOpsForThreadUpdates(
-    storeThreadInfos: RawThreadInfos,
+    storeThreadInfos: MinimallyEncodedRawThreadInfos,
     update: ThreadUpdateInfo,
   ) {
     if (_isEqual(storeThreadInfos[update.threadInfo.id])(update.threadInfo)) {
       return null;
     }
+    invariant(
+      update.threadInfo.minimallyEncoded,
+      'update threadInfo must be minimallyEncoded',
+    );
     return [
       {
         type: 'replace',
diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js
--- a/lib/types/thread-types.js
+++ b/lib/types/thread-types.js
@@ -246,10 +246,14 @@
   +pinnedCount: number,
 };
 
-export type ThreadStore = {
+export type LegacyThreadStore = {
   +threadInfos: RawThreadInfos,
 };
 
+export type ThreadStore = {
+  +threadInfos: MinimallyEncodedRawThreadInfos,
+};
+
 export type ClientDBThreadInfo = {
   +id: string,
   +type: number,
diff --git a/web/types/redux-types.js b/web/types/redux-types.js
--- a/web/types/redux-types.js
+++ b/web/types/redux-types.js
@@ -3,7 +3,7 @@
 import type { EntryStore, CalendarQuery } from 'lib/types/entry-types.js';
 import type { InviteLinksStore } from 'lib/types/link-types.js';
 import type { MessageStore } from 'lib/types/message-types.js';
-import type { ThreadStore } from 'lib/types/thread-types.js';
+import type { LegacyThreadStore, ThreadStore } from 'lib/types/thread-types.js';
 import type { CurrentUserInfo, UserInfos } from 'lib/types/user-types.js';
 import type { URLInfo } from 'lib/utils/url-utils.js';
 
@@ -13,7 +13,7 @@
   +navInfo: NavInfo,
   +currentUserInfo: CurrentUserInfo,
   +entryStore: EntryStore,
-  +threadStore: ThreadStore,
+  +threadStore: LegacyThreadStore,
   +userInfos: UserInfos,
   +messageStore: MessageStore,
   +pushApiPublicKey: ?string,