diff --git a/keyserver/src/shared/state-sync/current-user-state-sync-spec.js b/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
@@ -12,9 +12,13 @@
 
 export const currentUserStateSyncSpec: ServerStateSyncSpec<
   OldCurrentUserInfo | CurrentUserInfo,
+  OldCurrentUserInfo | CurrentUserInfo,
 > = Object.freeze({
   fetch(viewer: Viewer) {
     return fetchCurrentUserInfo(viewer);
   },
+  fetchFullSocketSyncPayload(viewer: Viewer) {
+    return fetchCurrentUserInfo(viewer);
+  },
   ...libSpec,
 });
diff --git a/keyserver/src/shared/state-sync/entries-state-sync-spec.js b/keyserver/src/shared/state-sync/entries-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/entries-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/entries-state-sync-spec.js
@@ -2,7 +2,11 @@
 
 import { serverEntryInfosObject } from 'lib/shared/entry-utils.js';
 import { entriesStateSyncSpec as libSpec } from 'lib/shared/state-sync/entries-state-sync-spec.js';
-import type { CalendarQuery, RawEntryInfos } from 'lib/types/entry-types.js';
+import type {
+  CalendarQuery,
+  RawEntryInfo,
+  RawEntryInfos,
+} from 'lib/types/entry-types.js';
 
 import type { ServerStateSyncSpec } from './state-sync-spec.js';
 import {
@@ -11,18 +15,27 @@
 } from '../../fetchers/entry-fetchers.js';
 import type { Viewer } from '../../session/viewer.js';
 
-export const entriesStateSyncSpec: ServerStateSyncSpec<RawEntryInfos> =
-  Object.freeze({
-    async fetch(
-      viewer: Viewer,
-      query: $ReadOnlyArray<CalendarQuery>,
-      ids?: $ReadOnlySet<string>,
-    ) {
-      if (ids) {
-        return fetchEntryInfosByID(viewer, ids);
-      }
-      const entriesResult = await fetchEntryInfos(viewer, query);
-      return serverEntryInfosObject(entriesResult.rawEntryInfos);
-    },
-    ...libSpec,
-  });
+export const entriesStateSyncSpec: ServerStateSyncSpec<
+  RawEntryInfos,
+  $ReadOnlyArray<RawEntryInfo>,
+> = Object.freeze({
+  async fetch(
+    viewer: Viewer,
+    query: $ReadOnlyArray<CalendarQuery>,
+    ids?: $ReadOnlySet<string>,
+  ) {
+    if (ids) {
+      return fetchEntryInfosByID(viewer, ids);
+    }
+    const entriesResult = await fetchEntryInfos(viewer, query);
+    return serverEntryInfosObject(entriesResult.rawEntryInfos);
+  },
+  async fetchFullSocketSyncPayload(
+    viewer: Viewer,
+    query: $ReadOnlyArray<CalendarQuery>,
+  ) {
+    const result = await fetchEntryInfos(viewer, query);
+    return result.rawEntryInfos;
+  },
+  ...libSpec,
+});
diff --git a/keyserver/src/shared/state-sync/state-sync-spec.js b/keyserver/src/shared/state-sync/state-sync-spec.js
--- a/keyserver/src/shared/state-sync/state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/state-sync-spec.js
@@ -5,11 +5,15 @@
 
 import type { Viewer } from '../../session/viewer.js';
 
-export type ServerStateSyncSpec<Infos, Info = empty> = {
+export type ServerStateSyncSpec<Infos, FullSocketSyncPayload, Info = empty> = {
   +fetch: (
     viewer: Viewer,
     calendarQuery: $ReadOnlyArray<CalendarQuery>,
     ids?: $ReadOnlySet<string>,
   ) => Promise<Infos>,
+  +fetchFullSocketSyncPayload: (
+    viewer: Viewer,
+    calendarQuery: $ReadOnlyArray<CalendarQuery>,
+  ) => Promise<FullSocketSyncPayload>,
   ...StateSyncSpec<Infos, Info>,
 };
diff --git a/keyserver/src/shared/state-sync/state-sync-specs.js b/keyserver/src/shared/state-sync/state-sync-specs.js
--- a/keyserver/src/shared/state-sync/state-sync-specs.js
+++ b/keyserver/src/shared/state-sync/state-sync-specs.js
@@ -7,7 +7,7 @@
 import { usersStateSyncSpec } from './users-state-sync-spec.js';
 
 export const serverStateSyncSpecs: {
-  +[string]: ServerStateSyncSpec<*, *>,
+  +[string]: ServerStateSyncSpec<*, *, *>,
 } = Object.freeze({
   threads: threadsStateSyncSpec,
   entries: entriesStateSyncSpec,
diff --git a/keyserver/src/shared/state-sync/threads-state-sync-spec.js b/keyserver/src/shared/state-sync/threads-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/threads-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/threads-state-sync-spec.js
@@ -8,16 +8,22 @@
 import { fetchThreadInfos } from '../../fetchers/thread-fetchers.js';
 import type { Viewer } from '../../session/viewer.js';
 
-export const threadsStateSyncSpec: ServerStateSyncSpec<RawThreadInfos> =
-  Object.freeze({
-    async fetch(
-      viewer: Viewer,
-      query: $ReadOnlyArray<CalendarQuery>,
-      ids?: $ReadOnlySet<string>,
-    ) {
-      const filter = ids ? { threadIDs: ids } : undefined;
-      const result = await fetchThreadInfos(viewer, filter);
-      return result.threadInfos;
-    },
-    ...libSpec,
-  });
+export const threadsStateSyncSpec: ServerStateSyncSpec<
+  RawThreadInfos,
+  RawThreadInfos,
+> = Object.freeze({
+  async fetch(
+    viewer: Viewer,
+    query: $ReadOnlyArray<CalendarQuery>,
+    ids?: $ReadOnlySet<string>,
+  ) {
+    const filter = ids ? { threadIDs: ids } : undefined;
+    const result = await fetchThreadInfos(viewer, filter);
+    return result.threadInfos;
+  },
+  async fetchFullSocketSyncPayload(viewer: Viewer) {
+    const result = await fetchThreadInfos(viewer);
+    return result.threadInfos;
+  },
+  ...libSpec,
+});
diff --git a/keyserver/src/shared/state-sync/users-state-sync-spec.js b/keyserver/src/shared/state-sync/users-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/users-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/users-state-sync-spec.js
@@ -3,23 +3,31 @@
 import { usersStateSyncSpec as libSpec } from 'lib/shared/state-sync/users-state-sync-spec.js';
 import type { CalendarQuery } from 'lib/types/entry-types.js';
 import type { UserInfos, UserInfo } from 'lib/types/user-types.js';
+import { values } from 'lib/utils/objects.js';
 
 import type { ServerStateSyncSpec } from './state-sync-spec.js';
 import { fetchKnownUserInfos } from '../../fetchers/user-fetchers.js';
 import type { Viewer } from '../../session/viewer.js';
 
-export const usersStateSyncSpec: ServerStateSyncSpec<UserInfos, UserInfo> =
-  Object.freeze({
-    fetch(
-      viewer: Viewer,
-      query: $ReadOnlyArray<CalendarQuery>,
-      ids?: $ReadOnlySet<string>,
-    ) {
-      if (ids) {
-        return fetchKnownUserInfos(viewer, [...ids]);
-      }
+export const usersStateSyncSpec: ServerStateSyncSpec<
+  UserInfos,
+  $ReadOnlyArray<UserInfo>,
+  UserInfo,
+> = Object.freeze({
+  fetch(
+    viewer: Viewer,
+    query: $ReadOnlyArray<CalendarQuery>,
+    ids?: $ReadOnlySet<string>,
+  ) {
+    if (ids) {
+      return fetchKnownUserInfos(viewer, [...ids]);
+    }
 
-      return fetchKnownUserInfos(viewer);
-    },
-    ...libSpec,
-  });
+    return fetchKnownUserInfos(viewer);
+  },
+  async fetchFullSocketSyncPayload(viewer: Viewer) {
+    const result = await fetchKnownUserInfos(viewer);
+    return values(result);
+  },
+  ...libSpec,
+});
diff --git a/keyserver/src/socket/socket.js b/keyserver/src/socket/socket.js
--- a/keyserver/src/socket/socket.js
+++ b/keyserver/src/socket/socket.js
@@ -59,17 +59,11 @@
 import { deleteCookie } from '../deleters/cookie-deleters.js';
 import { deleteUpdatesBeforeTimeTargetingSession } from '../deleters/update-deleters.js';
 import { jsonEndpoints } from '../endpoints.js';
-import { fetchEntryInfos } from '../fetchers/entry-fetchers.js';
 import {
   fetchMessageInfosSince,
   getMessageFetchResultFromRedisMessages,
 } from '../fetchers/message-fetchers.js';
-import { fetchThreadInfos } from '../fetchers/thread-fetchers.js';
 import { fetchUpdateInfos } from '../fetchers/update-fetchers.js';
-import {
-  fetchCurrentUserInfo,
-  fetchKnownUserInfos,
-} from '../fetchers/user-fetchers.js';
 import {
   newEntryQueryInputValidator,
   verifyCalendarQueryThreadIDs,
@@ -83,6 +77,7 @@
   isCookieMissingOlmNotificationsSession,
 } from '../session/cookies.js';
 import { Viewer } from '../session/viewer.js';
+import { serverStateSyncSpecs } from '../shared/state-sync/state-sync-specs.js';
 import { commitSessionUpdate } from '../updaters/session-updaters.js';
 import { assertSecureRequest } from '../utils/security-utils.js';
 import {
@@ -474,20 +469,20 @@
       isCookieMissingOlmNotificationsSession(viewer);
 
     if (!sessionInitializationResult.sessionContinued) {
-      const [threadsResult, entriesResult, currentUserInfo, knownUserInfos] =
-        await Promise.all([
-          fetchThreadInfos(viewer),
-          fetchEntryInfos(viewer, [calendarQuery]),
-          fetchCurrentUserInfo(viewer),
-          fetchKnownUserInfos(viewer),
-        ]);
+      const promises = Object.fromEntries(
+        values(serverStateSyncSpecs).map(spec => [
+          spec.hashKey,
+          spec.fetchFullSocketSyncPayload(viewer, [calendarQuery]),
+        ]),
+      );
+      const results = await promiseAll(promises);
       const payload: ServerStateSyncFullSocketPayload = {
         type: stateSyncPayloadTypes.FULL,
         messagesResult,
-        threadInfos: threadsResult.threadInfos,
-        currentUserInfo,
-        rawEntryInfos: entriesResult.rawEntryInfos,
-        userInfos: values(knownUserInfos),
+        threadInfos: results.threadInfos,
+        currentUserInfo: results.currentUserInfo,
+        rawEntryInfos: results.entryInfos,
+        userInfos: results.userInfos,
         updatesCurrentAsOf: oldUpdatesCurrentAsOf,
       };
       if (viewer.sessionChanged) {