diff --git a/lib/actions/activity-actions.js b/lib/actions/activity-actions.js
--- a/lib/actions/activity-actions.js
+++ b/lib/actions/activity-actions.js
@@ -1,12 +1,12 @@
 // @flow
 
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import type {
   ActivityUpdate,
   ActivityUpdateSuccessPayload,
   SetThreadUnreadStatusPayload,
   SetThreadUnreadStatusRequest,
 } from '../types/activity-types.js';
-import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
 
diff --git a/lib/actions/entry-actions.js b/lib/actions/entry-actions.js
--- a/lib/actions/entry-actions.js
+++ b/lib/actions/entry-actions.js
@@ -1,5 +1,9 @@
 // @flow
 
+import {
+  extractKeyserverIDFromID,
+  sortCalendarQueryPerKeyserver,
+} from '../keyserver-conn/keyserver-call-utils.js';
 import { localIDPrefix } from '../shared/message-utils.js';
 import type {
   RawEntryInfo,
@@ -16,10 +20,6 @@
   CalendarQueryUpdateResult,
 } from '../types/entry-types.js';
 import type { HistoryRevisionInfo } from '../types/history-types.js';
-import {
-  extractKeyserverIDFromID,
-  sortCalendarQueryPerKeyserver,
-} from '../utils/action-utils.js';
 import { dateFromString } from '../utils/date-utils.js';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call.js';
diff --git a/lib/actions/link-actions.js b/lib/actions/link-actions.js
--- a/lib/actions/link-actions.js
+++ b/lib/actions/link-actions.js
@@ -1,5 +1,6 @@
 // @flow
 
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import type {
   FetchInviteLinksResponse,
   InviteLinkVerificationRequest,
@@ -9,7 +10,6 @@
   DisableInviteLinkRequest,
   DisableInviteLinkPayload,
 } from '../types/link-types.js';
-import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import type { CallServerEndpoint } from '../utils/call-server-endpoint.js';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call.js';
diff --git a/lib/actions/message-actions.js b/lib/actions/message-actions.js
--- a/lib/actions/message-actions.js
+++ b/lib/actions/message-actions.js
@@ -2,6 +2,10 @@
 
 import invariant from 'invariant';
 
+import {
+  extractKeyserverIDFromID,
+  sortThreadIDsPerKeyserver,
+} from '../keyserver-conn/keyserver-call-utils.js';
 import type {
   FetchMessageInfosPayload,
   SendMessageResult,
@@ -22,10 +26,6 @@
   ToggleMessagePinRequest,
   ToggleMessagePinResult,
 } from '../types/thread-types.js';
-import {
-  extractKeyserverIDFromID,
-  sortThreadIDsPerKeyserver,
-} from '../utils/action-utils.js';
 import type { CallServerEndpointResultInfo } from '../utils/call-server-endpoint.js';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call.js';
diff --git a/lib/actions/message-report-actions.js b/lib/actions/message-report-actions.js
--- a/lib/actions/message-report-actions.js
+++ b/lib/actions/message-report-actions.js
@@ -1,10 +1,10 @@
 // @flow
 
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import type {
   MessageReportCreationRequest,
   MessageReportCreationResult,
 } from '../types/message-report-types.js';
-import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call.js';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
 
diff --git a/lib/actions/thread-actions.js b/lib/actions/thread-actions.js
--- a/lib/actions/thread-actions.js
+++ b/lib/actions/thread-actions.js
@@ -3,6 +3,7 @@
 import invariant from 'invariant';
 
 import genesis from '../facts/genesis.js';
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import type {
   ChangeThreadSettingsPayload,
   LeaveThreadPayload,
@@ -18,7 +19,6 @@
   RoleDeletionRequest,
   RoleDeletionPayload,
 } from '../types/thread-types.js';
-import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import type { CallServerEndpoint } from '../utils/call-server-endpoint.js';
 import type { CallKeyserverEndpoint } from '../utils/keyserver-call';
 import { useKeyserverCall } from '../utils/keyserver-call.js';
diff --git a/lib/actions/upload-actions.js b/lib/actions/upload-actions.js
--- a/lib/actions/upload-actions.js
+++ b/lib/actions/upload-actions.js
@@ -3,8 +3,8 @@
 import uuid from 'uuid';
 
 import blobService from '../facts/blob-service.js';
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import type { UploadMultimediaResult, Dimensions } from '../types/media-types';
-import { extractKeyserverIDFromID } from '../utils/action-utils.js';
 import { toBase64URL } from '../utils/base64.js';
 import {
   blobServiceUploadHandler,
diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -2,6 +2,11 @@
 
 import * as React from 'react';
 
+import {
+  extractKeyserverIDFromID,
+  sortThreadIDsPerKeyserver,
+  sortCalendarQueryPerKeyserver,
+} from '../keyserver-conn/keyserver-call-utils.js';
 import { preRequestUserStateSelector } from '../selectors/account-selectors.js';
 import threadWatcher from '../shared/thread-watcher.js';
 import type {
@@ -51,11 +56,6 @@
   PasswordUpdate,
   LoggedOutUserInfo,
 } from '../types/user-types.js';
-import {
-  extractKeyserverIDFromID,
-  sortThreadIDsPerKeyserver,
-  sortCalendarQueryPerKeyserver,
-} from '../utils/action-utils.js';
 import type {
   CallServerEndpoint,
   CallServerEndpointOptions,
diff --git a/lib/keyserver-conn/keyserver-call-utils.js b/lib/keyserver-conn/keyserver-call-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/keyserver-conn/keyserver-call-utils.js
@@ -0,0 +1,93 @@
+// @flow
+
+import invariant from 'invariant';
+
+import type { CalendarQuery } from '../types/entry-types.js';
+import type { NotDeletedFilter } from '../types/filter-types.js';
+
+function extractKeyserverIDFromID(id: string): string {
+  return id.split('|')[0];
+}
+
+function sortThreadIDsPerKeyserver(threadIDs: $ReadOnlyArray<string>): {
+  +[keyserverID: string]: $ReadOnlyArray<string>,
+} {
+  const results: { [string]: string[] } = {};
+  for (const threadID of threadIDs) {
+    const keyserverID = extractKeyserverIDFromID(threadID);
+    invariant(keyserverID, 'keyserver data missing from thread id');
+    if (results[keyserverID] === undefined) {
+      results[keyserverID] = [];
+    }
+    results[keyserverID].push(threadID);
+  }
+  return results;
+}
+
+type CalendarThreadFilterWithWritableThreadIDs = {
+  +type: 'threads',
+  +threadIDs: string[],
+};
+type CalendarFilterWithWritableThreadIDs =
+  | NotDeletedFilter
+  | CalendarThreadFilterWithWritableThreadIDs;
+type CalendarQueryWithWritableFilters = {
+  +startDate: string,
+  +endDate: string,
+  +filters: CalendarFilterWithWritableThreadIDs[],
+};
+function sortCalendarQueryPerKeyserver(
+  calendarQuery: CalendarQuery,
+  keyserverIDs: $ReadOnlyArray<string>,
+): {
+  +[keyserverID: string]: CalendarQuery,
+} {
+  const { startDate, endDate, filters } = calendarQuery;
+  const results: { [string]: CalendarQueryWithWritableFilters } = {};
+
+  for (const keyserverID of keyserverIDs) {
+    results[keyserverID] = {
+      startDate,
+      endDate,
+      filters: [],
+    };
+  }
+
+  for (const filter of filters) {
+    if (filter.type === 'not_deleted') {
+      for (const keyserverID in results) {
+        results[keyserverID].filters.push({ type: 'not_deleted' });
+      }
+    } else if (filter.type === 'threads') {
+      for (const threadID of filter.threadIDs) {
+        const keyserverID = extractKeyserverIDFromID(threadID);
+        if (results[keyserverID] === undefined) {
+          continue;
+        }
+        let threadFilter = results[keyserverID].filters.find(
+          flt => flt.type === 'threads',
+        );
+        invariant(
+          !threadFilter || threadFilter.type === 'threads',
+          'should only match CalendarThreadFilter',
+        );
+        if (!threadFilter) {
+          threadFilter = { type: 'threads', threadIDs: [] };
+          results[keyserverID].filters.push(threadFilter);
+        }
+
+        threadFilter.threadIDs.push(threadID);
+      }
+    } else {
+      console.warn('unhandled filter in sortCalendarQueryPerKeyserver');
+    }
+  }
+
+  return results;
+}
+
+export {
+  extractKeyserverIDFromID,
+  sortThreadIDsPerKeyserver,
+  sortCalendarQueryPerKeyserver,
+};
diff --git a/lib/utils/action-utils.test.js b/lib/keyserver-conn/keyserver-call-utils.test.js
rename from lib/utils/action-utils.test.js
rename to lib/keyserver-conn/keyserver-call-utils.test.js
--- a/lib/utils/action-utils.test.js
+++ b/lib/keyserver-conn/keyserver-call-utils.test.js
@@ -3,7 +3,7 @@
 import {
   extractKeyserverIDFromID,
   sortCalendarQueryPerKeyserver,
-} from './action-utils.js';
+} from './keyserver-call-utils.js';
 import type { CalendarQuery } from '../types/entry-types';
 
 describe('extractKeyserverIDFromID', () => {
diff --git a/lib/reducers/calendar-filters-reducer.js b/lib/reducers/calendar-filters-reducer.js
--- a/lib/reducers/calendar-filters-reducer.js
+++ b/lib/reducers/calendar-filters-reducer.js
@@ -19,6 +19,7 @@
   registerActionTypes,
   tempIdentityLoginActionTypes,
 } from '../actions/user-actions.js';
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import {
   filteredThreadIDs,
   nonThreadCalendarFilters,
@@ -44,10 +45,7 @@
   type ClientUpdateInfo,
   processUpdatesActionType,
 } from '../types/update-types.js';
-import {
-  extractKeyserverIDFromID,
-  setNewSessionActionType,
-} from '../utils/action-utils.js';
+import { setNewSessionActionType } from '../utils/action-utils.js';
 import { filterThreadIDsBelongingToCommunity } from '../utils/drawer-utils.react.js';
 
 export default function reduceCalendarFilters(
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
@@ -10,6 +10,7 @@
 import { messageSpecs } from './messages/message-specs.js';
 import { threadIsGroupChat } from './thread-utils.js';
 import { useStringForUser } from '../hooks/ens-cache.js';
+import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import { contentStringForMediaArray } from '../media/media-utils.js';
 import type { ChatMessageInfoItem } from '../selectors/chat-selectors.js';
 import { threadInfoSelector } from '../selectors/thread-selectors.js';
@@ -43,7 +44,6 @@
 } from '../types/messages/reaction.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,
diff --git a/lib/utils/action-utils.js b/lib/utils/action-utils.js
--- a/lib/utils/action-utils.js
+++ b/lib/utils/action-utils.js
@@ -24,8 +24,6 @@
 } from '../types/account-types.js';
 import type { PlatformDetails } from '../types/device-types.js';
 import type { Endpoint, SocketAPIHandler } from '../types/endpoints.js';
-import type { CalendarQuery } from '../types/entry-types.js';
-import type { NotDeletedFilter } from '../types/filter-types.js';
 import type { LoadingOptions, LoadingInfo } from '../types/loading-types.js';
 import type {
   ActionPayload,
@@ -39,10 +37,6 @@
 } from '../types/session-types.js';
 import type { CurrentUserInfo } from '../types/user-types.js';
 
-function extractKeyserverIDFromID(id: string): string {
-  return id.split('|')[0];
-}
-
 let nextPromiseIndex = 0;
 
 export type ActionTypes<
@@ -541,83 +535,6 @@
   socketAPIHandler = passedSocketAPIHandler;
 }
 
-function sortThreadIDsPerKeyserver(threadIDs: $ReadOnlyArray<string>): {
-  +[keyserverID: string]: $ReadOnlyArray<string>,
-} {
-  const results: { [string]: string[] } = {};
-  for (const threadID of threadIDs) {
-    const keyserverID = extractKeyserverIDFromID(threadID);
-    invariant(keyserverID, 'keyserver data missing from thread id');
-    if (results[keyserverID] === undefined) {
-      results[keyserverID] = [];
-    }
-    results[keyserverID].push(threadID);
-  }
-  return results;
-}
-
-type CalendarThreadFilterWithWritableThreadIDs = {
-  +type: 'threads',
-  +threadIDs: string[],
-};
-type CalendarFilterWithWritableThreadIDs =
-  | NotDeletedFilter
-  | CalendarThreadFilterWithWritableThreadIDs;
-type CalendarQueryWithWritableFilters = {
-  +startDate: string,
-  +endDate: string,
-  +filters: CalendarFilterWithWritableThreadIDs[],
-};
-function sortCalendarQueryPerKeyserver(
-  calendarQuery: CalendarQuery,
-  keyserverIDs: $ReadOnlyArray<string>,
-): {
-  +[keyserverID: string]: CalendarQuery,
-} {
-  const { startDate, endDate, filters } = calendarQuery;
-  const results: { [string]: CalendarQueryWithWritableFilters } = {};
-
-  for (const keyserverID of keyserverIDs) {
-    results[keyserverID] = {
-      startDate,
-      endDate,
-      filters: [],
-    };
-  }
-
-  for (const filter of filters) {
-    if (filter.type === 'not_deleted') {
-      for (const keyserverID in results) {
-        results[keyserverID].filters.push({ type: 'not_deleted' });
-      }
-    } else if (filter.type === 'threads') {
-      for (const threadID of filter.threadIDs) {
-        const keyserverID = extractKeyserverIDFromID(threadID);
-        if (results[keyserverID] === undefined) {
-          continue;
-        }
-        let threadFilter = results[keyserverID].filters.find(
-          flt => flt.type === 'threads',
-        );
-        invariant(
-          !threadFilter || threadFilter.type === 'threads',
-          'should only match CalendarThreadFilter',
-        );
-        if (!threadFilter) {
-          threadFilter = { type: 'threads', threadIDs: [] };
-          results[keyserverID].filters.push(threadFilter);
-        }
-
-        threadFilter.threadIDs.push(threadID);
-      }
-    } else {
-      console.warn('unhandled filter in sortCalendarQueryPerKeyserver');
-    }
-  }
-
-  return results;
-}
-
 export {
   useDispatchActionPromise,
   setNewSessionActionType,
@@ -626,7 +543,4 @@
   registerActiveSocket,
   useServerCall,
   bindCookieAndUtilsIntoCallServerEndpoint,
-  extractKeyserverIDFromID,
-  sortThreadIDsPerKeyserver,
-  sortCalendarQueryPerKeyserver,
 };
diff --git a/native/chat/settings/thread-settings-push-notifs.react.js b/native/chat/settings/thread-settings-push-notifs.react.js
--- a/native/chat/settings/thread-settings-push-notifs.react.js
+++ b/native/chat/settings/thread-settings-push-notifs.react.js
@@ -8,6 +8,7 @@
   updateSubscriptionActionTypes,
   useUpdateSubscription,
 } from 'lib/actions/user-actions.js';
+import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js';
 import { deviceTokenSelector } from 'lib/selectors/keyserver-selectors.js';
 import type {
   SubscriptionUpdateRequest,
@@ -15,10 +16,7 @@
 } from 'lib/types/subscription-types.js';
 import type { ThreadInfo } from 'lib/types/thread-types.js';
 import type { DispatchActionPromise } from 'lib/utils/action-utils.js';
-import {
-  useDispatchActionPromise,
-  extractKeyserverIDFromID,
-} from 'lib/utils/action-utils.js';
+import { useDispatchActionPromise } from 'lib/utils/action-utils.js';
 
 import SingleLine from '../../components/single-line.react.js';
 import SWMansionIcon from '../../components/swmansion-icon.react.js';
diff --git a/web/redux/action-types.js b/web/redux/action-types.js
--- a/web/redux/action-types.js
+++ b/web/redux/action-types.js
@@ -1,7 +1,7 @@
 // @flow
 
+import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js';
 import { defaultCalendarFilters } from 'lib/types/filter-types.js';
-import { extractKeyserverIDFromID } from 'lib/utils/action-utils.js';
 import { useKeyserverCall } from 'lib/utils/keyserver-call.js';
 import type { CallKeyserverEndpoint } from 'lib/utils/keyserver-call.js';
 import type { URLInfo } from 'lib/utils/url-utils.js';