Short answer: a passwordless phone login is a sound fit for a gaming storefront, provided the Express/Node.js backend owns the SMS OTP resend cooldown, maximum verification attempts, and anti-abuse counters rather than accepting any of those decisions from the browser or game client.

The page arrives after a payment has settled: the player can see a completed order, but the session that should expose the receipt is stuck behind repeated code requests. On-call sees a burst of sends for one phone, several IP addresses, and one device. The useful question isn't "did the SMS API respond?" It is whether the authentication state machine allowed work that policy should have rejected before a send occurred.

That distinction sets the design. Express should expose explicit send-code, verify-code, resend-code, and lockout states, persist only the minimum state needed to enforce them, and make the database authoritative for expiry and counters. Don't let a client-provided timer become a security boundary. The visible countdown is UX; the stored deadline is policy.

How does an Express Node.js SMS OTP resend flow enforce cooldowns?

Model the flow before choosing a provider. A code request begins in ready, moves to code_sent, and can end in verified, expired, or locked. A resend is a transition from code_sent to a fresh code_sent, but only after the backend checks its increasing cooldown and daily caps across phone, IP, and device. A verification failure increments a server-side attempt counter; reaching the configured maximum moves the record to locked. A successful verification consumes the challenge so it cannot authenticate a second session.