diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js
--- a/lib/shared/message-utils.js
+++ b/lib/shared/message-utils.js
@@ -47,6 +47,7 @@
 } from '../types/minimally-encoded-thread-permissions-types.js';
 import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js';
 import type { UserInfos } from '../types/user-types.js';
+import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import {
   type EntityText,
   ET,
@@ -699,6 +700,25 @@
   return !messageSpecs[message.type].canBeRenderedIndependently;
 }
 
+function findNewestMessageTimePerKeyserver(
+  messageInfos: $ReadOnlyArray<RawMessageInfo>,
+): { [keyserverID: string]: number } {
+  const timePerKeyserver: { [keyserverID: string]: number } = {};
+
+  for (const messageInfo of messageInfos) {
+    const keyserverID = extractKeyserverIDFromID(messageInfo.threadID);
+
+    if (
+      !timePerKeyserver[keyserverID] ||
+      timePerKeyserver[keyserverID] < messageInfo.time
+    ) {
+      timePerKeyserver[keyserverID] = messageInfo.time;
+    }
+  }
+
+  return timePerKeyserver;
+}
+
 export {
   localIDPrefix,
   messageKey,
@@ -732,4 +752,5 @@
   isInvalidPinSource,
   isInvalidPinSourceForThread,
   isUnableToBeRenderedIndependently,
+  findNewestMessageTimePerKeyserver,
 };
diff --git a/lib/shared/message-utils.test.js b/lib/shared/message-utils.test.js
--- a/lib/shared/message-utils.test.js
+++ b/lib/shared/message-utils.test.js
@@ -4,10 +4,14 @@
   isInvalidSidebarSource,
   isInvalidPinSource,
   isUnableToBeRenderedIndependently,
+  findNewestMessageTimePerKeyserver,
 } from './message-utils.js';
 import { messageSpecs } from '../shared/messages/message-specs.js';
+import type {
+  RawMessageInfo,
+  RawSidebarSourceMessageInfo,
+} from '../types/message-types';
 import { messageTypes } from '../types/message-types-enum.js';
-import type { RawSidebarSourceMessageInfo } from '../types/message-types.js';
 import type { RawAddMembersMessageInfo } from '../types/messages/add-members.js';
 import type { RawChangeRoleMessageInfo } from '../types/messages/change-role.js';
 import type { RawChangeSettingsMessageInfo } from '../types/messages/change-settings.js';
@@ -758,3 +762,41 @@
     });
   });
 });
+
+describe('findNewestMessageTimePerKeyserver', () => {
+  it('should return the time of the newest message for every keyserver', () => {
+    const messages: $ReadOnlyArray<RawMessageInfo> = [
+      {
+        type: 0,
+        threadID: '256|100',
+        creatorID: '256',
+        time: 4,
+        text: 'test',
+      },
+      {
+        type: 0,
+        threadID: '1|100',
+        creatorID: '256',
+        time: 2,
+        text: 'test',
+      },
+      {
+        type: 0,
+        threadID: '1|100',
+        creatorID: '256',
+        time: 3,
+        text: 'test',
+      },
+      {
+        type: 0,
+        threadID: '256|100',
+        creatorID: '256',
+        time: 1,
+        text: 'test',
+      },
+    ];
+
+    const result = { ['256']: 4, ['1']: 3 };
+    expect(findNewestMessageTimePerKeyserver(messages)).toEqual(result);
+  });
+});