diff --git a/keyserver/src/creators/account-creator.js b/keyserver/src/creators/account-creator.js
--- a/keyserver/src/creators/account-creator.js
+++ b/keyserver/src/creators/account-creator.js
@@ -14,15 +14,8 @@
 import type {
   UserDetail,
   ReservedUsernameMessage,
-  SignedIdentityKeysBlob,
 } from 'lib/types/crypto-types.js';
-import type {
-  PlatformDetails,
-  DeviceTokenUpdateRequest,
-} from 'lib/types/device-types.js';
-import type { CalendarQuery } from 'lib/types/entry-types.js';
 import { messageTypes } from 'lib/types/message-types-enum.js';
-import type { SIWESocialProof } from 'lib/types/siwe-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
 import { ServerError } from 'lib/utils/errors.js';
 import { values } from 'lib/utils/objects.js';
@@ -222,57 +215,6 @@
   };
 }
 
-export type ProcessSIWEAccountCreationRequest = {
-  +address: string,
-  +calendarQuery: CalendarQuery,
-  +deviceTokenUpdateRequest?: ?DeviceTokenUpdateRequest,
-  +platformDetails: PlatformDetails,
-  +socialProof: SIWESocialProof,
-  +signedIdentityKeysBlob?: ?SignedIdentityKeysBlob,
-};
-// Note: `processSIWEAccountCreation(...)` assumes that the validity of
-//       `ProcessSIWEAccountCreationRequest` was checked at call site.
-async function processSIWEAccountCreation(
-  viewer: Viewer,
-  request: ProcessSIWEAccountCreationRequest,
-): Promise<string> {
-  const { calendarQuery, signedIdentityKeysBlob } = request;
-  await verifyCalendarQueryThreadIDs(calendarQuery);
-
-  const time = Date.now();
-  const deviceToken = request.deviceTokenUpdateRequest
-    ? request.deviceTokenUpdateRequest.deviceToken
-    : viewer.deviceToken;
-  const [id] = await createIDs('users', 1);
-  const newUserRow = [id, request.address, request.address, time];
-  const newUserQuery = SQL`
-    INSERT INTO users(id, username, ethereum_address, creation_time)
-    VALUES ${[newUserRow]}
-  `;
-  const [userViewerData] = await Promise.all([
-    createNewUserCookie(id, {
-      platformDetails: request.platformDetails,
-      deviceToken,
-      socialProof: request.socialProof,
-      signedIdentityKeysBlob,
-    }),
-    deleteCookie(viewer.cookieID),
-    dbQuery(newUserQuery),
-  ]);
-  viewer.setNewCookie(userViewerData);
-
-  await setNewSession(viewer, calendarQuery, 0);
-  await processAccountCreationCommon(viewer);
-
-  ignorePromiseRejections(
-    createAndSendReservedUsernameMessage([
-      { username: request.address, userID: id },
-    ]),
-  );
-
-  return id;
-}
-
 async function processAccountCreationCommon(viewer: Viewer) {
   const admin = await thisKeyserverAdmin();
 
@@ -340,6 +282,6 @@
 
 export {
   createAccount,
-  processSIWEAccountCreation,
   processAccountCreationCommon,
+  createAndSendReservedUsernameMessage,
 };
diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js
--- a/keyserver/src/responders/user-responders.js
+++ b/keyserver/src/responders/user-responders.js
@@ -82,6 +82,7 @@
 } from 'lib/utils/crypto-utils.js';
 import { ServerError } from 'lib/utils/errors.js';
 import { values } from 'lib/utils/objects.js';
+import { ignorePromiseRejections } from 'lib/utils/promises.js';
 import {
   getPublicKeyFromSIWEStatement,
   isValidSIWEMessage,
@@ -105,10 +106,11 @@
   verifyCalendarQueryThreadIDs,
 } from './entry-responders.js';
 import {
+  createAndSendReservedUsernameMessage,
   processAccountCreationCommon,
   createAccount,
-  processSIWEAccountCreation,
 } from '../creators/account-creator.js';
+import createIDs from '../creators/id-creator.js';
 import {
   createOlmSession,
   persistFreshOlmSession,
@@ -602,6 +604,7 @@
     signedIdentityKeysBlob,
     initialNotificationsEncryptedMessage,
     doNotRegister,
+    watchedIDs,
   } = request;
   const calendarQuery = normalizeCalendarQuery(request.calendarQuery);
 
@@ -612,9 +615,11 @@
   }
 
   // 2. Check if there's already a user for this ETH address.
-  const existingUserID = await fetchUserIDForEthereumAddress(
-    siweMessage.address,
-  );
+  //    Verify calendarQuery.
+  const [existingUserID] = await Promise.all([
+    fetchUserIDForEthereumAddress(siweMessage.address),
+    verifyCalendarQueryThreadIDs(calendarQuery),
+  ]);
   if (!existingUserID && doNotRegister) {
     throw new ServerError('account_does_not_exist');
   }
@@ -692,29 +697,29 @@
     siweMessageSignature: signature,
   };
 
-  // 9. Create account with call to `processSIWEAccountCreation(...)`
-  //    if address does not correspond to an existing user.
-  let userID = existingUserID;
-  if (!userID) {
-    const siweAccountCreationRequest = {
-      address: siweMessage.address,
-      calendarQuery,
-      deviceTokenUpdateRequest,
-      platformDetails,
-      socialProof,
-    };
-    userID = await processSIWEAccountCreation(
-      viewer,
-      siweAccountCreationRequest,
-    );
-  }
+  // 9. Create account if address does not correspond to an existing user.
+  const userID = await (async () => {
+    if (existingUserID) {
+      return existingUserID;
+    }
+    const time = Date.now();
+    const [id] = await createIDs('users', 1);
+    const newUserRow = [id, siweMessage.address, siweMessage.address, time];
+    const newUserQuery = SQL`
+      INSERT INTO users(id, username, ethereum_address, creation_time)
+      VALUES ${[newUserRow]}
+    `;
+
+    await dbQuery(newUserQuery);
+    return id;
+  })();
 
   // 10. Complete login with call to `processSuccessfulLogin(...)`.
-  return await processSuccessfulLogin({
+  const result = await processSuccessfulLogin({
     viewer,
-    platformDetails: request.platformDetails,
-    deviceTokenUpdateRequest: request.deviceTokenUpdateRequest,
-    watchedIDs: request.watchedIDs,
+    platformDetails,
+    deviceTokenUpdateRequest,
+    watchedIDs,
     userID,
     calendarQuery,
     socialProof,
@@ -722,6 +727,21 @@
     initialNotificationsEncryptedMessage,
     shouldMarkPoliciesAsAcceptedAfterCookieCreation: !existingUserID,
   });
+
+  // 11. Create threads with call to `processAccountCreationCommon(...)`,
+  //     if the account has just been registered. Also, set the username as
+  //     reserved.
+  if (!existingUserID) {
+    await processAccountCreationCommon(viewer);
+
+    ignorePromiseRejections(
+      createAndSendReservedUsernameMessage([
+        { username: siweMessage.address, userID },
+      ]),
+    );
+  }
+
+  return result;
 }
 
 export const keyserverAuthRequestInputValidator: TInterface<KeyserverAuthRequest> =