When people say “Don’t build your own auth,” they don’t mean outsource everything to a third-party SaaS.
And when others say “Build your own auth,” they don’t mean reinvent the wheel.
Here is how I think about it.
The Middle Ground
Use a library like NextAuth, Passport.js, or your stack’s equivalent.
Keep your user data in your own database.
The moment you hand it to Auth0 or Clerk, you’re locked in, paying per active user, and surrendering control over your own users.
That’s a bad trade.
Once you own it, keep login options minimal.
Every method you add is another attack surface.
For most products, Google OAuth is enough.
Let Google handle identity verification. They’re better at it than you are.
Passwords Are Not as Simple as They Look
Email and password seems like the safe default, but it’s the hardest to run correctly, especially on Node or Python backends.
Bcrypt and Argon2 are deliberately slow.
Under load, they’ll hurt performance.
If you must support it, add a CAPTCHA — not to annoy users, but to nudge them toward the simpler path.
2FA
For 2FA, skip SMS.
SIM swapping is a real risk, international delivery is unreliable, and costs add up.
Authenticator apps are boring, but they work.
The Part Most People Overlook
Here’s the part most people overlook:
Get your stable identifiers right early.
If a user logs in with Google today and GitHub tomorrow, you need to recognize it’s the same person.
Email isn’t reliable. People change it.
GitHub, Google, and Instagram all provide internal IDs that never change.
Store those, map them to your own user ID, and you’ll never accidentally lock someone out of their account.
The Simple Version
Own your auth.
Keep it simple.
Get the identifiers right.