The Auth Tax: Why I Stopped Rebuilding Login Flows for Every Product
Every product I shipped in year one reimplemented auth. Year two I started extracting it. Year three I built my own service. Here is what that path actually cost, and when you should follow it.
Gagan Deep Singh
Founder | GLINR Studios
The first product I shipped in Glincker had its own auth. Email plus password, sessions, password reset flow, the full stack. It took me most of a weekend to get right. I did not think about it again until the second product.
The second product also had its own auth. Different stack because I had learned about httpOnly cookies in the meantime. Still a weekend. Still working. Still mine.
By product six I was copy-pasting auth code between repos. By product nine I had three slightly different bug fixes for the same session-rotation race that I had to backport each time I touched the code. By product twelve I realized I had spent roughly thirty weekends of my life writing sign-in forms. That was the moment I built Kavachos.
The thirty-weekend math
I did the accounting because a cofounder of mine kept teasing me that I was reinventing identity. He was right. Here is the actual breakdown for each product:
| Auth component | Time per product | Products touched | Total hours |
|---|---|---|---|
| Signup + email verification | 6 hours | 12 | 72 |
| Login + session handling | 5 hours | 12 | 60 |
| Password reset flow | 4 hours | 12 | 48 |
| OAuth providers (Google, GitHub) | 8 hours | 8 | 64 |
| MFA / 2FA | 10 hours | 4 | 40 |
| Admin role gates | 3 hours | 10 | 30 |
| Bug fixes over a year | ~10 hours | 12 | 120 |
Roughly 434 hours of auth work across twelve products. Thirty weekends if you count an eight-hour weekend, which you should not.
The time was not wasted exactly. Each implementation taught me something. By the third product the flow was tight. By the sixth I had opinions about session rotation. By the ninth I could build the whole thing without looking anything up.
But the learning stopped compounding around product four. After that, every new auth implementation was just dragging the same rock up the same hill.
The wrong abstraction era
Before I built Kavachos I tried three wrong abstractions.
A shared auth library. I extracted my auth code into an npm package. It worked, sort of. The problem: every product needed slightly different UI, slightly different fields on the user table, slightly different OAuth scopes. The library became a mess of config options. Using it was only marginally faster than starting fresh.
A shared auth service with a REST API. I stood up a Fastify server that my other products called. This was better architecturally but worse operationally. I now had to deploy and monitor an eighth service. If it went down, twelve products went down. I did not want that blast radius.
Auth0 and Clerk. I tried both. They were both excellent. They were also priced for companies that charge more per customer than I do. Passing $0.02 per MAU to a prosumer product that monetizes at $5 per month is fine. Passing it to an OSS tool with 10,000 free users would have eaten any margin I had. The free tiers were tight enough that I would have hit limits within months.
All three taught me what I actually needed. A service I controlled, run cheaply, with enough flexibility for the long tail of per-product quirks.
What Kavachos actually solved
Kavachos is the auth server I should have built at product three. By the time I built it, I already had twelve reasons to know exactly what it needed:
- OAuth 2.1 / OIDC compliant. So any future product gets standards-based integration for free.
- 27 OAuth providers plus SAML. Because I kept running into "can you add Apple sign-in" requests.
- Per-product user tables. Because one product's user schema should not pollute another's.
- Self-hosted. Because I was not going to route sensitive auth traffic through someone else's servers.
- Scoped tokens for AI agents. Because this was the new requirement that finally forced my hand. MCP was taking off and my products needed auth for agents as well as humans.
The last bullet is the one that made the project unavoidable. Every existing auth service was built before AI agents were first-class users. Scoping tokens for an agent that can talk to your API is a different problem from scoping tokens for a human. Building on top of Clerk, even if I could afford it, would have meant bolting that capability on. Starting fresh let me design it in.
When to build your own auth
Almost never, honestly. Building your own auth service is overkill for most solo founders. Here is the test I would give you:
- If you are on product one or two, use Clerk or Auth0. Pay the money. Ship the thing.
- If you are on product three to five, start abstracting your auth into a shared library. Accept that it will be imperfect.
- If you are on product six to ten with similar user models, consider a shared internal auth service. The blast radius is real but the speed gain is bigger.
- If you are on product ten-plus with unusual requirements (agents, unusual scope patterns, strict self-hosting), building your own becomes reasonable. Not before.
The trap is building your own at product two because it sounds fun. It is the same overthinking trap I wrote about last week. The right move at product two is the boring one. Clerk. Ship. Learn what your users actually need. Come back to the auth question once you know.
What surprised me about running my own
Three things I did not expect.
Most of the work is not in the happy path. Signup works in a weekend. The edge cases eat months. Password reset emails that land in spam filters. Oauth callbacks that fail because a user's corporate VPN strips a cookie. Rate-limiting attackers without locking out legitimate users. None of this is fun. All of it is necessary.
Maintenance is half the job. OAuth providers change their APIs. Security standards evolve. The crypto module in Node deprecates a function you were relying on. I spend roughly a day a month on auth maintenance just to keep everything working. Auth0 would have absorbed that.
Compliance creeps up on you. Once you host auth for more than a handful of users, you start thinking about GDPR, SOC 2, audit logs. I did not think about these until I was deep in. Building them in later is harder than building them in early.
The advice I would have taken
If I could send a message back to the version of myself who was about to start Kavachos at product two, I would say: do not. Use Clerk. You do not have enough information yet to design the right abstraction. You will know in three years which features you actually need. Build it then.
The thirty weekends of pre-Kavachos auth work were not wasted, but they were not optimal either. Half of that time could have gone into the products themselves. The other half taught me what mattered. The ratio could have been better.
The part nobody tells you
Every major product decision has this shape: the right thing to do is obvious in retrospect and invisible in the moment. Auth is one of the most obvious examples because it is so ubiquitous that the compounding cost of reinventing it is brutal, and the compounding benefit of solving it once is enormous.
If you are building a solo studio and you have not consolidated your auth, that is your next move. It does not have to be Kavachos. It can be Clerk, Auth0, Supabase Auth, or a library you trust. The important thing is to stop paying the tax, one product at a time.
The tax compounds. The solution also compounds. Pick the side of the equation you want on your balance sheet.