Cosmic

Clerk vs. rolling your own auth: what three production apps taught us

Saad Ahmed · Founder6 min read

Short answer

As of September 2026, for most new apps, use a managed provider such as Clerk for authentication and keep authorization in your own code. Across three custom production apps, the one with hand-built auth needed 3,339 lines of auth code and about 45 security tickets, and an audit still found its live API giving admin rights to anonymous callers. The two apps on Clerk had sign-in working within two days, and their later auth work moved to webhooks, latency and agent access.

Key takeaways

  • Hand-built auth passed 292 tests and still shipped with four flaws a pentest found, plus no working login in production.
  • On Clerk, sign-in worked a day after the first commit, and the password policy was three dashboard settings with no code change.
  • Clerk moves the work to the seams: missed webhooks, unsubscribed session events, upstream failures and per-request latency.
  • Verifying Clerk's 60-second session token locally cut auth calls to Clerk to zero and brought signed-in pages to a p95 of 90 to 122 ms.
  • Authorization stays yours either way: roles, tenancy, row-level security and agent tokens.

The first app I shipped had hand-built authentication. I rolled my own because I didn't know any better (or about Clerk!).

I knew the issues of rolling your own auth: you would not get full security. But I didn't know any better as a non-developer. This is a common mistake vibe coders make.

Since then, Cosmic has built two more custom production apps on Clerk: a talent marketplace and an agent work coordinator. Between the three, there's enough git history and ticket data to compare the two approaches on real work.

Written in September 2026. If you're reading this at a future date, best practices may have changed. Clerk's features, token lifetimes and pricing, and OWASP's guidance, are described as they stood that month.

Hand-built auth vs. Clerk across three custom production apps (September 2026)
Hand-built (B2B data platform)Clerk (talent marketplace)Clerk (agent work coordinator)
Sign-in workingLogin endpoint 17 days after the auth codeDay 12 days after adding Clerk
Auth code we wrote3,339 linesAbout 300 linesMostly authorization, webhooks and agent tokens
Security ticketsAbout 45, plus 4 pentest fixesAlmost none on credentialsAlmost none on credentials
Password reset, MFA, one-time codesNone builtIncludedIncluded
Where the later work wentSessions, CSRF, lockout, secret rotationRouter and token-refresh quirksWebhooks, latency, agent access
Authorization (who sees what)CustomCustomCustom

Hand-built auth took 3,339 lines and about 45 security tickets

The first app is a B2B data platform with a Python API and a React dashboard. Its own strategy doc said to adopt an identity provider, because "OIDC/SSO, orgs, MFA, sessions, and API keys are not product differentiation." The code went the other way.

On a single day in June, about ten auth features merged: signed session tokens, cross-tenant access fixes, CSRF protection, cookies with refresh-token rotation, session timeouts and rate limits. A security batch of roughly 45 tickets followed, covering session fixation, account enumeration, timing attacks, webhook replay, secret rotation and brute-force lockout.

Case in point:

  • 3,339 lines of core auth code, in Python and JavaScript.
  • 292 auth and security test functions.
  • 4 database tables just for session state.
  • 0 password reset, email verification, MFA or social sign-in flows.

A pentest and an audit found what the tests missed

A pentest suite and a review against the OWASP Application Security Verification Standard turned up four flaws in that code:

  • Session state lived in each server process's memory. A token revoked on one worker still worked on another, and every revocation was lost on restart.
  • The CSRF check let writes through when a request had neither an Origin nor a Referer header.
  • One static signing secret with no rotation path. A leak would have forced every user to sign in again.
  • The rate limiter didn't know about logins, so nothing slowed down password guessing.

We fixed each one. Then an audit in July found a bigger problem. The auth machinery was real and tested, but no endpoint turned a username and password into a session, the enforcement flag was unset in production and the fallback role was admin. The live API was giving admin rights to anonymous callers. A login endpoint shipped 17 days after the auth code did.

The one operator password was stored as an unsalted SHA-256 hash. OWASP's password storage guidance (as of September 2026) calls for a slow, salted algorithm such as Argon2id or bcrypt.

Every item on that list is a problem an auth provider solved years ago. A non-developer (me) can't see any of them in code that passes its own tests.

With Clerk, sign-in worked on day one

The talent marketplace used Clerk from its first commit. Sign-in worked the next day, and server-verified sessions with isolated application accounts ran in the hosted app by day three. The code connecting Clerk to the app is about 300 lines.

Its password policy shows what changes. Minimum length, a strength check and a check against known breached passwords are three settings in the Clerk dashboard. The ticket closed with "No code change."

The agent work coordinator ran on a shared API key for its first four months. Clerk went in on September 6. It worked in development two days later and ran in production on a custom domain 13 days after that. On September 21 we deleted the old auth path: 194 files changed, 3,077 tests passing and a 401 for every unauthenticated request.

The coordinator is where the choice mattered most, because people and AI agents both sign in to it. Clerk was suggested to me by a few friends, and after looking into it, especially how it handled human plus agent sessions, that it had a native MCP connector to work with and native OTP, I was sold. Plus the billing features for per-user sign-up.

Clerk moves the work to webhooks, latency and agents

Clerk took credentials off our list. The tickets that followed were about the seams between Clerk and our own code:

  • Missed webhooks. A workspace is created when Clerk sends an organization webhook. When one went missing, the organization sat stuck in provisioning until we added a repair path.
  • An unsubscribed event. Session webhooks were never subscribed, so a sign-out reached the app only when a 60-second cache expired.
  • Upstream failures. A brief Clerk failure once blanked the whole workspace screen. We narrowed Clerk to an identity boundary so a hiccup there no longer takes the app down with it.
  • Latency. Signed-in pages waited 500 to 800 ms because every request made three calls to Clerk.
  • Agents during the cutover. Removing the old shared key broke agent access until agents moved to OAuth.
  • Frontend quirks. The marketplace's router rewrote Clerk's SSO callback URL mid-sign-in, and a session token that refreshes about once a minute remounted the signed-in app and threw away half-typed edits.

I'm still working on optimizing Clerk for latency, optimizing for repeat auth checks, but the recent tickets have latency down to mere milliseconds. The fix was to verify people locally against Clerk's session token, which lasts 60 seconds as of September 2026, and trust agent OAuth tokens for up to an hour. A load test showed 0 calls per second to Clerk and signed-in pages at a p95 of 90 to 122 ms.

Authorization stays in your code either way

In all three apps, the rules for who sees what stayed custom.

The talent marketplace keeps recruiter details in Clerk metadata as display data only. No client metadata, URL parameter or company domain can grant recruiter access. A recruiter verifies an email and gets a server-side enrollment record first.

The coordinator maps Clerk organizations to workspaces, checks membership against Clerk's API rather than trusting role claims in the token, and enforces tenancy with Postgres row-level security. Agent tokens are its own, scoped to one workspace.

That's where engineering time belongs. Who can see which record is specific to your product, and sessions and password resets are the same in every app.

When building your own auth still makes sense

Clerk has real downsides:

  • You depend on Clerk's uptime. Design so a Clerk failure degrades sign-in and leaves the rest of the app running.
  • Your user IDs come from Clerk. Keep your own account table keyed to them, as both of our apps do, so a future move is a mapping job.
  • Cost grows with users. As of September 2026, Clerk's free plan covers 50,000 monthly retained users per app, and the Pro plan is $25 a month plus $0.02 for each user past that. Check the pricing page against your growth plan before you commit.
  • Some products need to own identity: strict data-residency rules, or a product where identity is the thing you sell.
Which way to go, by situation (September 2026)
If your app...Our call
Was vibe-coded and is heading to its first real usersUse Clerk or a similar provider from day one
Lets both people and AI agents sign inUse a provider that can issue OAuth tokens to agents; Clerk does this for MCP servers
Already has hand-built auth that fails the checks belowMove to a provider; it's usually less work than patching
Must keep identity data in your own infrastructureHost identity yourself, and budget for a pentest before launch
Sells identity as the productBuild it, with security engineers on the team

For an AI-built app headed to its first real users, none of those downsides outweigh starting on a provider.

Five checks to run on your own app's auth

  • Password hashing. Find the function that stores passwords. If it's SHA-256 or MD5, it needs replacing.
  • Sign-out. Sign out on one device. Another signed-in device should stop working within a minute or two.
  • Record IDs. Change a record ID in the URL to one that belongs to another account. You should get an error.
  • Guessing. Enter 20 wrong passwords in a row. Something should slow you down.
  • Enforcement. Call your API with no session at all. Every private endpoint should return a 401.

If any of those fail and the auth is hand-built, moving to a provider is usually less work than patching it.

If I did it again: Clerk all the way

If I did it again, Clerk all the way.

Authentication is one of the first things we check when we take an AI-built app to production. The agent work coordinator and talent marketplace case studies show the rest of those builds. If your app rolled its own auth, contact us.

FAQ

Should I build my own authentication or use Clerk?

As of September 2026, use Clerk or a similar provider unless identity is your product or data-residency rules require you to host it. Hand-built auth in our first app took 3,339 lines and about 45 security tickets and still had flaws a pentest found.

Does Clerk handle authorization too?

Clerk tells you who the user is and which organization they're in. Rules about which records they can read, and tenancy enforcement such as row-level security, stay in your code.

Does Clerk slow down an app?

It can if every request calls Clerk's API. Our signed-in pages waited 500 to 800 ms until we verified the 60-second session token locally; a load test then showed 0 Clerk calls per second and a page p95 of 90 to 122 ms.

Is Clerk free?

As of September 2026, Clerk's free plan covers up to 50,000 monthly retained users per app. The Pro plan costs $25 a month and adds $0.02 for each retained user past 50,000.

Is Clerk safe to use?

Clerk issues signed session tokens that expire after 60 seconds (as of September 2026), and your server verifies each one. The auth problems we hit on Clerk were in our own integration, such as missed webhooks and caching, plus one brief upstream failure. Your app's authorization checks still decide what a signed-in user can reach.

Can AI agents sign in with Clerk?

Yes. As of September 2026, Clerk can act as the OAuth server for an MCP server, so agents get their own scoped tokens alongside people's sessions.

Sources

  1. Clerk docs: session tokens
  2. Clerk docs: build an MCP server with Clerk
  3. Clerk docs: Clerk Billing
  4. Clerk pricing (September 2026)
  5. OWASP Password Storage Cheat Sheet
  6. OWASP Session Management Cheat Sheet
  7. OWASP Application Security Verification Standard
Saad Ahmed

Founder of Cosmic. Nearly 15 years in strategy, management and sales as a digital strategist, director of sales and product manager. He closed over $25M in new revenue at VMware Pivotal Labs, launched digital products at Capital One, and helped Viget grow from 30 to 75 people. He started Cosmic and built the Revenue Design® process after advising friends whose companies struggled to close deals and keep revenue steady.