I Tried Shipping Passkey Login on a Client Project: What Actually Happened
A client of mine runs a small subscription web app, and this year the recurring support ticket wasn’t a bug — it was password resets. Forgotten passwords, reused passwords getting flagged by breach-monitoring tools, the occasional phishing attempt against their support inbox pretending to be a locked-out user. Passkeys have looked like the obvious answer for a while now — full browser and OS support, no shared secret to phish, no password to reuse across sites. So I actually implemented them on this project instead of just reading another “passkeys are the future” post, and the results were more mixed than the enthusiasm you see online would suggest.
The technical implementation itself was the easy part, which surprised me. I used a WebAuthn library on the Node backend to handle registration and authentication ceremonies, added the browser-side navigator.credentials calls, and stored the credential public keys against user accounts. A weekend of focused work got a working passkey flow running end-to-end in a dev environment. If you’ve done any auth work before, the actual cryptography and protocol handling isn’t the hard part anymore — the libraries have matured enough that this is a well-trodden path now, not a research project.
Where it got genuinely complicated was account recovery, and I underestimated this badly. What happens when someone’s phone with their passkey breaks, gets lost, or gets replaced? With a password, recovery is annoying but conceptually simple — reset via email. With a passkey tied to a device’s secure enclave, losing that device without a synced backup means losing the credential entirely unless you’ve planned for it. I ended up keeping password-plus-email-OTP as a permanent fallback rather than a passkey-only system, specifically because I didn’t want to design myself into a corner where a lost phone means a locked-out paying customer with no clean recovery path.
Cross-device sync behavior differs enough between ecosystems that I had to test far more combinations than I expected. A passkey created on an iPhone syncs through iCloud Keychain; one created on Android syncs through Google Password Manager; a passkey created on a work laptop with a hardware key behaves differently again. Testing “does this work” isn’t one test case, it’s realistically eight or nine across browsers, OS versions, and whether someone’s using a personal or a locked-down corporate device. I found at least two combinations — an older Android WebView and a corporate-managed Chrome profile with policy restrictions — where the flow silently failed in ways that gave the user a confusing error instead of a clear explanation.
The part that matched what I’d read about stalling adoption was the actual user reaction, not the technology. When I offered passkey login as an option, I watched a handful of non-technical users try it during a soft rollout, and the confusion wasn’t about the mechanics — Face ID or a fingerprint prompt is intuitive enough — it was about the concept. “Wait, so I don’t have a password for this anymore? What if I get a new phone?” is a completely reasonable question that a lot of onboarding copy doesn’t actually answer. Several users who started the passkey setup flow abandoned it partway through, not because it broke, but because they weren’t sure what they were agreeing to.
In the first month after the soft rollout, adoption looked like this: a small minority of tech-savvy users switched over almost immediately, most people ignored the option entirely and kept using their password, and a few tried it and reverted back to password login within days. That’s roughly consistent with the “stalling adoption” narrative that’s been showing up in industry write-ups this year — the technology works, but a lot of ordinary users don’t yet have a clear mental model for what a passkey actually is or why it’s better than what they’re already using.
The thing that moved the needle more than any backend work was rewriting the onboarding copy. My first version explained passkeys in terms of the technology — “a cryptographic credential stored on your device.” Nobody cared. The version that actually got more people to try it just said “sign in with Face ID or your fingerprint instead of typing a password” and showed exactly what the prompt would look like before they tapped anything. This wasn’t an engineering lesson so much as a reminder that a genuinely better technical solution doesn’t sell itself just because it’s technically better.
My actual recommendation for anyone building this into a client project right now: build it as an addition, not a replacement, and don’t skip the recovery story. Passkeys are absolutely worth offering — the security properties are real and the implementation cost with modern libraries is genuinely low. But treating them as a full replacement for password-based login today, for a general consumer audience that isn’t already primed to understand the concept, would have meant designing a worse experience for most of this client’s users, not a better one.
I’ll keep watching adoption on this project over the next few months, because I think the picture changes over a longer window than one soft rollout can show. The users who did switch to passkeys haven’t gone back, and support tickets from that group have dropped to roughly zero, which is a meaningfully good outcome even at a low adoption rate. My guess is this follows the same curve two-factor authentication did years ago — slow uptake at first, mostly power users, until enough of the ecosystem defaults to it that it stops feeling like an unusual choice. I’m just not going to pretend that curve has already played out based on one month of data from one client’s app.