The direct answer

A changed session key does not make retained anonymous data trustworthy. Follow the framework’s documented login transition, retain only explicitly allowed harmless preferences, and rebuild user, workspace and action authority from authenticated application records. Treat logout, other sessions and in-flight work according to their separate evidence.

A successful login can preserve the wrong kind of state

A fictional AI console allows an anonymous visitor to choose a display language and prepare a proposed export. After the visitor signs in, the interface shows the preferred language and the old proposal. Preserving the first can be useful; inheriting authority to execute the second would be a different decision.

This original worksheet selects the standard server-side database session backend and built-in authentication functions documented in Django 6.0. Both source pages display documentation version 6.0; no patch release, installed framework, middleware or backend configuration was inspected. The positive path begins anonymous and signs in as the intended authenticated user U-A. It does not cover switching directly between two authenticated users.

Read the key and data operations separately

The Django sessions documentation says cycle_key creates a new session key while retaining current data, and login calls it to mitigate session fixation. It describes flush as deleting current session data and the session cookie. These are different operations.

The authentication documentation explicitly says anonymous-session data is retained after login. Its logout description says all session data for the current request is removed. Those statements support the selected ordinary transition; they do not establish every internal login branch, a cross-device revocation mechanism or concurrent-request safety.

Do not replace normal framework login with a custom cookie change or assume that another manual cycle_key call cleans application values. A server-side store can hold data derived from untrusted requests. Storage location and a new key do not change that data’s origin or grant an approval.

Divide pre-login state by purpose

Invent anonymous context S-ANON with language preference L-A and proposal reference P-A. These are inert labels, not session identifiers, cookie contents, real proposals or user records. U-A later has current membership in workspace W-A, established through trusted authenticated application state.

Original pre-login retention policy — PROPOSED_UNRUN
Application-owned dataProposed treatment at login
Display-language preference L-AValidate against the small permitted language set; retain only for presentation
Anonymous proposal reference P-ADiscard from the executable workflow; do not promote it to an approved action
Workspace or user hintTreat as an untrusted selection request; resolve identity and membership anew
Claimed approval, spending credit or privileged roleNever migrate as authority; consult the responsible trusted records
Unrecognized application key or nested metadataExclude under the explicit allowlist rather than copy wholesale

Keeping L-A must not select a model provider, widen a budget or change document access. If a supposedly cosmetic setting changes an important workflow consequence, remove it from this harmless-preference category and review that consequence separately.

Define the permitted ordinary transition

For this proposed design, capture and validate only the allowed application preference while the request is still anonymous. Remove the application’s pre-login workflow values before they can be consumed as authenticated work. Continue through the configured normal authentication path and built-in login for successfully authenticated U-A, preserving framework-owned session handling.

After that transition, keep only validated L-A in the application preference slot, resolve W-A from current membership and create a new action A-A under current authorization and required review. P-A may be discarded as an execution reference without pretending that its separate stored draft or previously delivered copies were deleted. If retaining draft content is later wanted, specify an independently reviewed ownership-transfer workflow.

This allowlist and cleanup sequence is application policy, not automatic Django behavior. Apply it only to application-owned values. Django reserves underscore-prefixed session keys for internal use; do not sweep away authentication internals, override request.session or bypass framework security controls to implement the example.

Persistence also needs evidence. The sessions page documents that nested-object mutation alone does not mark a session modified and that a response with status 500 does not save the session. A future implementation must demonstrate its supported assignment/deletion and successful persistence path before reporting migration complete. No database transaction, save operation or race was exercised here.

Review eight inert transition cards

Original S-ANON to U-A worksheet — all PROPOSED_UNRUN
Inert conditionProposed decision
Ordinary intended login, allowed L-A and current U-A/W-A rightsRetain presentation preference; permit only newly authorized and reviewed A-A
Key changed but anonymous P-A remains in application dataDo not execute P-A; rotation did not grant approval
Inherited value claims U-B, W-B or approval grantedReject authority migration; derive current identity, membership and review separately
An authenticated earlier-user context is presentHold outside this anonymous-entry profile; require a separately supported transition, not a guessed login branch
Logout occurs, then an old initiation or action reference is presentedEnforce the reference’s original binding; never attach it to the next signed-in user
Only this browser session’s operation is evidencedReport that scope; other devices, sessions and connector grants remain unverified
Old request, overlapping write or save outcome is unresolvedHold the affected workflow outcome; no race or effect-recall claim
Login succeeds but W-A action permission is absentDeny A-A independently of authentication success

Keep logout and current action authority precise

For the chosen documented logout path, current-request session data is cleaned out. If the application intentionally starts a new anonymous preference afterward, make that a fresh narrow decision rather than restoring a prior user’s workflow bundle. Do not copy stale approval or OAuth-initiation references into the new context.

This guide makes no authentication-hash, password-change, other-user-switch, global logout or cross-device invalidation claim. An earlier request can already be in flight, and an external effect may already have been admitted. Key rotation and session cleanup cannot establish that those effects were undone. Unsupported backend and concurrent-write behavior stays unknown.

The separate browser action-admission contract and exact current object/approval checks still apply after login. A retained preference, an authenticated flag or an old workspace selection cannot replace them.

All cases remain unrun: no Django import, login, logout, session, cookie, database, configuration, browser, account, API/model or runtime fixture operation occurred. Boundary is prelaunch and does not claim a shipped session manager. Its synthetic policy, export and approval-status checks establish different behavior.

Primary sources

Official references supporting the guidance. Examples in this guide are synthetic and are not reports of a production incident.

  1. Django 6.0: How to use sessions
  2. Django 6.0: Using the authentication system