Frontmatter yaml
---
title: Zero-downtime token migration
owner: Identity Platform
status: Proposed
target: 2026-Q3
---
Zero-downtime token migration
This fictional plan shows how a team can replace session cookies with signed access tokens without interrupting active users. The rollout is deliberately phased: compatibility first, migration second, cleanup last.
Note
This is a demonstration document. The systems, metrics, and contacts below are illustrative rather than production guidance.
Outcome
Goals
- Keep existing sessions valid throughout the migration.
- Make rollback a configuration change, not a deployment.
- Give support a clear explanation for every rejected request.
Non-goals
- Replacing the identity provider.
- Redesigning account recovery.
- Supporting
indefinitepermanent legacy sessions.
- Success
- At least 99.95% of authenticated requests complete without a token-related retry.
- Rollback
- Operators can restore cookie-first validation within five minutes.
Migration flow
flowchart LR
A[Cookie session] --> B[Dual validation]
B --> C[Token preferred]
C --> D[Token only]
B -. rollback .-> A
C -. rollback .-> B
Every phase has an explicit observation window. Promotion is manual until the error budget and support signals agree.
Compatibility contract
| Client state | Read cookie | Read token | Issue token | Result |
|---|---|---|---|---|
| Existing session | Yes | No | Yes | Transparent |
| Migrated session | Yes | Yes | Refresh | Token-first |
| New authentication | No | Yes | Yes | Token-only |
| Invalid credentials | No | No | No | Reauthenticate |
Important
Token and cookie validation must share the same revocation source. Running two independent authorization models would make rollback unsafe.
Delivery tracking
The rollout is coordinated in #184. Dual-validation middleware lands in PR #231, followed by token-first authentication in PR #248. The mobile client dependency is tracked separately in octo-mobile/auth-client#77.
These references use the fictional octo-org/identity-platform repository
configured for this demonstration.
Implementation
1. Add dual validation
The middleware accepts either credential while recording which path succeeded. The public handler contract remains unchanged.
func authenticate(r *http.Request) (*Identity, error) {
if token := bearerToken(r); token != "" {
return tokens.Validate(r.Context(), token)
}
return sessions.Validate(r.Context(), r)
}
- Define token claims and clock-skew policy.
- Add structured outcomes for both validators.
- Shadow-validate tokens without changing request decisions.
- Enable dual validation for internal users.
2. Migrate active sessions
On a successful cookie request, issue a short-lived token and let the client adopt it on its next request. Limit each migration cohort to 10% of eligible sessions per hour.
Warning
Do not infer migration success from token issuance alone. Count the first request authenticated by that token.
3. Prefer tokens
After two stable observation windows, check tokens before cookies. Keep cookie fallback enabled until the oldest supported client has crossed one complete release cycle.1
4. Remove compatibility code
- Disable new cookie creation.
- Wait through the maximum session lifetime.
- Remove cookie validation and migration metrics.
- Archive the operational dashboard and decision log.
Observability
| Signal | Promotion gate | Rollback threshold |
|---|---|---|
| Authentication failures | Below 0.05% | Above 0.20% |
| Token validation latency | p95 under 20ms | p95 above 50ms |
| Cookie fallback rate | Below 2% | Above 10% |
| Related support contacts | No increase | Five in 30 minutes |
The dashboard separates invalid credentials, expired credentials, verifier errors, and dependency timeouts. Aggregating them as “authentication failed” would hide the failure mode we need to act on.
Rollback
- Set
auth_preference=cookiein the runtime configuration. - Confirm cookie-first traffic exceeds 95% within five minutes.
- Preserve token issuance logs for analysis.
- Open an incident only if user-visible failures remain elevated.
Caution
Never revoke all issued tokens as the first rollback step. Existing clients may already have discarded their cookies.
Open questions
- Should service-to-service tokens use the same signing keys?
- Who owns the final legacy-session deletion approval?
- Do mobile clients need an additional release cycle?
Questions and rollout decisions go to [email protected].
-
For this example, one release cycle means fourteen days with no supported client version older than the token-capable release. ↩︎