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
@@ -247,8 +247,10 @@
   viewer.setNewCookie(userViewerData);
 
   await setNewSession(viewer, calendarQuery, 0);
-
-  await processAccountCreationCommon(viewer);
+  await Promise.all([
+    viewerAcknowledgmentUpdater(viewer, policyTypes.tosAndPrivacyPolicy),
+    processAccountCreationCommon(viewer),
+  ]);
 
   ignorePromiseRejections(
     createAndSendReservedUsernameMessage([
@@ -259,68 +261,17 @@
   return id;
 }
 
-export type ProcessOLMAccountCreationRequest = {
-  +userID: string,
-  +username: string,
-  +walletAddress?: ?string,
-  +calendarQuery: CalendarQuery,
-  +deviceTokenUpdateRequest?: ?DeviceTokenUpdateRequest,
-  +platformDetails: PlatformDetails,
-  +signedIdentityKeysBlob: SignedIdentityKeysBlob,
-};
-// Note: `processOLMAccountCreation(...)` assumes that the validity of
-//       `ProcessOLMAccountCreationRequest` was checked at call site.
-async function processOLMAccountCreation(
-  viewer: Viewer,
-  request: ProcessOLMAccountCreationRequest,
-): Promise<void> {
-  const { calendarQuery, signedIdentityKeysBlob } = request;
-  await verifyCalendarQueryThreadIDs(calendarQuery);
-
-  const time = Date.now();
-  const deviceToken = request.deviceTokenUpdateRequest
-    ? request.deviceTokenUpdateRequest.deviceToken
-    : viewer.deviceToken;
-  const newUserRow = [
-    request.userID,
-    request.username,
-    request.walletAddress,
-    time,
-  ];
-  const newUserQuery = SQL`
-    INSERT INTO users(id, username, ethereum_address, creation_time)
-    VALUES ${[newUserRow]}
-  `;
-  const [userViewerData] = await Promise.all([
-    createNewUserCookie(request.userID, {
-      platformDetails: request.platformDetails,
-      deviceToken,
-      signedIdentityKeysBlob,
-    }),
-    deleteCookie(viewer.cookieID),
-    dbQuery(newUserQuery),
-  ]);
-  viewer.setNewCookie(userViewerData);
-
-  await setNewSession(viewer, calendarQuery, 0);
-
-  await processAccountCreationCommon(viewer);
-}
-
 async function processAccountCreationCommon(viewer: Viewer) {
   const admin = await thisKeyserverAdmin();
 
-  await Promise.all([
-    updateThread(
-      createScriptViewer(admin.id),
-      {
-        threadID: genesis().id,
-        changes: { newMemberIDs: [viewer.userID] },
-      },
-      { forceAddMembers: true, silenceMessages: true, ignorePermissions: true },
-    ),
-    viewerAcknowledgmentUpdater(viewer, policyTypes.tosAndPrivacyPolicy),
-  ]);
+  await updateThread(
+    createScriptViewer(admin.id),
+    {
+      threadID: genesis().id,
+      changes: { newMemberIDs: [viewer.userID] },
+    },
+    { forceAddMembers: true, silenceMessages: true, ignorePermissions: true },
+  );
 
   const [privateThreadResult, ashoatThreadResult] = await Promise.all([
     createPrivateThread(viewer),
@@ -375,4 +326,8 @@
   await rustAPI.addReservedUsernames(stringifiedMessage, signature);
 }
 
-export { createAccount, processSIWEAccountCreation, processOLMAccountCreation };
+export {
+  createAccount,
+  processSIWEAccountCreation,
+  processAccountCreationCommon,
+};
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
@@ -11,6 +11,7 @@
   baseLegalPolicies,
   policies,
   policyTypeValidator,
+  policyTypes,
 } from 'lib/facts/policies.js';
 import { mixedRawThreadInfoValidator } from 'lib/permissions/minimally-encoded-raw-thread-info-validators.js';
 import { hasMinCodeVersion } from 'lib/shared/version-utils.js';
@@ -104,14 +105,13 @@
   verifyCalendarQueryThreadIDs,
 } from './entry-responders.js';
 import {
-  processOLMAccountCreation,
+  processAccountCreationCommon,
   createAccount,
   processSIWEAccountCreation,
 } from '../creators/account-creator.js';
 import {
   createOlmSession,
   persistFreshOlmSession,
-  createAndPersistOlmSession,
 } from '../creators/olm-session-creator.js';
 import { dbQuery, SQL } from '../database/database.js';
 import { deleteAccount } from '../deleters/account-deleters.js';
@@ -308,7 +308,7 @@
   +signedIdentityKeysBlob?: ?SignedIdentityKeysBlob,
   +initialNotificationsEncryptedMessage?: string,
   +pickledContentOlmSession?: string,
-  +cookieHasBeenSet?: boolean,
+  +shouldMarkPoliciesAsAcceptedAfterCookieCreation?: boolean,
 };
 
 async function processSuccessfulLogin(
@@ -325,20 +325,30 @@
     signedIdentityKeysBlob,
     initialNotificationsEncryptedMessage,
     pickledContentOlmSession,
-    cookieHasBeenSet,
+    shouldMarkPoliciesAsAcceptedAfterCookieCreation,
   } = params;
 
+  // Olm sessions have to be created before createNewUserCookie is called,
+  // to avoid propagating a user cookie in case session creation fails
+  const olmNotifSession = await (async () => {
+    if (initialNotificationsEncryptedMessage && signedIdentityKeysBlob) {
+      return await createOlmSession(
+        initialNotificationsEncryptedMessage,
+        'notifications',
+      );
+    }
+    return null;
+  })();
+
   const newServerTime = Date.now();
   const deviceToken = deviceTokenUpdateRequest
     ? deviceTokenUpdateRequest.deviceToken
     : viewer.deviceToken;
+
   const setNewCookiePromise = (async () => {
-    if (cookieHasBeenSet) {
-      return;
-    }
     const [userViewerData] = await Promise.all([
       createNewUserCookie(userID, {
-        platformDetails: platformDetails,
+        platformDetails,
         deviceToken,
         socialProof,
         signedIdentityKeysBlob,
@@ -347,8 +357,18 @@
     ]);
     viewer.setNewCookie(userViewerData);
   })();
+  const policiesCheckAndUpdate = (async () => {
+    if (shouldMarkPoliciesAsAcceptedAfterCookieCreation) {
+      await setNewCookiePromise;
+      await viewerAcknowledgmentUpdater(
+        viewer,
+        policyTypes.tosAndPrivacyPolicy,
+      );
+    }
+    return await fetchNotAcknowledgedPolicies(userID, baseLegalPolicies);
+  })();
   const [notAcknowledgedPolicies] = await Promise.all([
-    fetchNotAcknowledgedPolicies(userID, baseLegalPolicies),
+    policiesCheckAndUpdate,
     setNewCookiePromise,
   ]);
 
@@ -375,14 +395,10 @@
   if (calendarQuery) {
     await setNewSession(viewer, calendarQuery, newServerTime);
   }
-  const olmNotifSessionPromise = (async () => {
-    if (
-      viewer.cookieID &&
-      initialNotificationsEncryptedMessage &&
-      signedIdentityKeysBlob
-    ) {
-      await createAndPersistOlmSession(
-        initialNotificationsEncryptedMessage,
+  const persistOlmNotifSessionPromise = (async () => {
+    if (olmNotifSession && viewer.cookieID) {
+      await persistFreshOlmSession(
+        olmNotifSession,
         'notifications',
         viewer.cookieID,
       );
@@ -391,7 +407,7 @@
   // `pickledContentOlmSession` is created in `keyserverAuthResponder(...)` in
   // order to authenticate the user. Here, we simply persist the session if it
   // exists.
-  const olmContentSessionPromise = (async () => {
+  const persistOlmContentSessionPromise = (async () => {
     if (viewer.cookieID && pickledContentOlmSession) {
       await persistFreshOlmSession(
         pickledContentOlmSession,
@@ -426,8 +442,8 @@
     entriesPromise,
     fetchKnownUserInfos(viewer),
     fetchLoggedInUserInfo(viewer),
-    olmNotifSessionPromise,
-    olmContentSessionPromise,
+    persistOlmNotifSessionPromise,
+    persistOlmContentSessionPromise,
   ]);
 
   const rawEntryInfos = entriesResult ? entriesResult.rawEntryInfos : null;
@@ -728,8 +744,6 @@
   const {
     userID,
     deviceID,
-    deviceTokenUpdateRequest,
-    platformDetails,
     initialContentEncryptedMessage,
     initialNotificationsEncryptedMessage,
     doNotRegister,
@@ -744,6 +758,7 @@
       getContentSigningKey(),
       verifyUserLoggedIn(),
       getRustAPI(),
+      verifyCalendarQueryThreadIDs(calendarQuery),
     ]);
   if (!existingUsername && doNotRegister) {
     throw new ServerError('account_does_not_exist');
@@ -780,18 +795,16 @@
     throw new ServerError('invalid_identity_keys_blob');
   }
 
-  // 3. Create content olm session. (The notif session is not required for auth
-  //    and will be created later in `processSuccessfulLogin(...)`.)
+  // 3. Create content olm session. (The notif session was introduced first and
+  //    as such is created in legacy auth responders as well. It's factored out
+  //    into in the shared utility `processSuccessfulLogin(...)`.)
   const pickledContentOlmSessionPromise = createOlmSession(
     initialContentEncryptedMessage,
     'content',
     identityKeys.primaryIdentityPublicKeys.curve25519,
   );
 
-  // 4. Create account with call to `processOLMAccountCreation(...)`
-  //    if username does not correspond to an existing user. If we successfully
-  //    create a new account, we set `cookieHasBeenSet` to true to avoid
-  //    creating a new cookie again in `processSuccessfulLogin`.
+  // 4. Create account if username does not correspond to an existing user.
   const signedIdentityKeysBlob: SignedIdentityKeysBlob = {
     payload: inboundKeysForUser.payload,
     signature: inboundKeysForUser.payloadSignature,
@@ -800,16 +813,19 @@
     if (existingUsername) {
       return;
     }
-    const olmAccountCreationRequest = {
+
+    const time = Date.now();
+    const newUserRow = [
       userID,
-      username: username,
-      walletAddress: inboundKeysForUser.walletAddress,
-      signedIdentityKeysBlob,
-      calendarQuery,
-      deviceTokenUpdateRequest,
-      platformDetails,
-    };
-    await processOLMAccountCreation(viewer, olmAccountCreationRequest);
+      username,
+      inboundKeysForUser.walletAddress,
+      time,
+    ];
+    const newUserQuery = SQL`
+      INSERT INTO users(id, username, ethereum_address, creation_time)
+      VALUES ${[newUserRow]}
+  `;
+    await dbQuery(newUserQuery);
   })();
 
   const [pickledContentOlmSession] = await Promise.all([
@@ -818,7 +834,7 @@
   ]);
 
   // 5. Complete login with call to `processSuccessfulLogin(...)`.
-  return await processSuccessfulLogin({
+  const result = await processSuccessfulLogin({
     viewer,
     platformDetails: request.platformDetails,
     deviceTokenUpdateRequest: request.deviceTokenUpdateRequest,
@@ -828,8 +844,16 @@
     signedIdentityKeysBlob,
     initialNotificationsEncryptedMessage,
     pickledContentOlmSession,
-    cookieHasBeenSet: !existingUsername,
+    shouldMarkPoliciesAsAcceptedAfterCookieCreation: !existingUsername,
   });
+
+  // 6. Create threads with call to `processAccountCreationCommon(...)`,
+  //    if the account has just been registered.
+  if (!existingUsername) {
+    await processAccountCreationCommon(viewer);
+  }
+
+  return result;
 }
 
 export const updatePasswordRequestInputValidator: TInterface<UpdatePasswordRequest> =