OTP expiry and resend interval must be visible
Aliases: OTP TTL · resend cooldown · code expired copy
What it is
A one-time code sits under two clocks: expiry (after which it cannot sign anyone in) and resend interval (how long before another code may be requested). Making them visible means both remaining times, and what to do when expiry hits, are on the input screen—not only a post-submit “invalid code.” This entry is about clock visibility. It is not about how the code is pasted, and not about how many wrong guesses lock the attempt.
Why it happens
OTP places people inside an invisible countdown. SMS delay, mail in spam, and an app switch all desynchronize “I think it is still live” from “the server already killed it.” Failure copy that only says “incorrect” cannot separate a typo, expiry, and delivery to the wrong number. A resend control with no interval is mashed, then rate-limited, which looks like a broken system. The clocks have different jobs: expiry bounds the guess window; resend interval bounds channel cost. Collapsing them into one “try again in 60 seconds” makes people discard a still-valid code, or wait for a resend that will not come after the code is already dead. A visible denominator makes waiting plannable.
Studying it
Manipulate whether clock information appears and whether the two clocks are separate, and measure behavior near expiry plus how people explain the failure.
Independent variables: remaining-valid seconds shown, a separate resend countdown, copy that distinguishes “expired” from “mismatch.” Dependent variables: submits after expiry, wasted resend taps, abandonments that treat delay as failure, accuracy of “should I wait or request again.”
Lab networks are fast and SMS delay is near zero, so the desync rarely appears. Inject delay at the application layer or shrink TTL to tens of seconds. Faster completion with a countdown is not the goal; correct attribution is: resend when expired, wait or paste the arrived code while it is still valid.
Where it stops holding
TOTP from an authenticator app is already a rolling clock; stacking a “valid for five minutes” line fights the token window. Follow the authenticator period instead of inventing a second TTL. Screen-reader users cannot use a one-second ticking readout; complement it with low-frequency updates or a static “valid for about N minutes.” Email OTP has high latency variance; a too-short displayed TTL produces “it was dead when I opened the mail.” The clock must cover typical channel lag, not just compute time. If the OS kills the login page, clock state must rebuild on return rather than pretend the send just happened.
Applying it
- Show both “this code is valid until hh:mm:ss” and “resend in N seconds” as independent countdowns; say whether a resend invalidates the old code.
- Branch submit failures: mismatch, expired, not yet delivered when that can be detected. Do not collapse them into “wrong code.”
- When resend issues a new code, invalidate the old one and reset the expiry display so people do not paste a stale SMS.
- Verify by shrinking TTL to an observable window and watching someone uninvolved in the design act after death: they should resend on their own and explain why. Rapid resend taps before the interval ends should be blocked with remaining wait time, not fail silently.
Related
- Within the group: H6.03.1 OTP fields must accept paste and autofill · H6.03.3 SMS failure needs a fallback channel · H6.03.4 A magic link must expire after one use so forwarding cannot reuse it · H6.03.5 Limit OTP guesses to stop brute-force enumeration · H6.03.6 Magic links and OTP codes are not equivalent authenticators · H6.03.7 Passwordless login still needs a device-side confirmation against intercepted links
- Adjacent: H6.11 Password recovery and reset · H3.02 Three elements of error messages
- Search terms:
OTP expiry·resend cooldown·one-time password TTL
Cards in the same group
- H6.03.1OTP fields must accept paste and autofill
- H6.03.3SMS failure needs a fallback channel
- H6.03.4A magic link must expire after one use so forwarding cannot reuse it
- H6.03.5Limit OTP guesses to stop brute-force enumeration
- H6.03.6Magic links and OTP codes are not equivalent authenticators
- H6.03.7Passwordless login still needs a device-side confirmation against intercepted links