TL;DR: The $24,000-a-year Clerk math still circulating is dead. Since Clerk's February 2026 repricing, 50,000 Monthly Retained Users are free and 100K MRU costs about $1,025/mo. Migrate to Better Auth when an operational trigger is live: outage coupling, the 5 req/s rate limit, or webhook-sync drift. Budget about two engineer-weeks on a live product.
The decision:
Migrate when: Clerk outages take your product down, the 5 req/s limit bites, or webhook sync drifts
Risk: bcrypt-to-scrypt hash mismatch locks migrated users out; cutover invalidates every active session
Best for: live products past 50,000 MRU that already own their user database
Migrating Clerk to Better Auth at month nine is a decision most teams price with numbers that died in February 2026. Correct the numbers and the verdict flips: below Clerk's free 50,000 MRU, stay unless an operational failure is pushing you out; past it, the migration pays back within months. Here is the corrected math, from ShipKit, a SaaS boilerplate that ships Better Auth pre-wired.
Clerk's February 2026 changelog raised the free tier from 10,000 MAU to 50,000 Monthly Retained Users, so 100K MRU now bills at about $1,025 a month, not the $2,025 the stale calculators still report. For a developer building the team's migration case, the first mistake is copying the SERP's $24k-a-year figure into the proposal: the number dies the moment anyone opens Clerk's pricing page, and the proposal's credibility dies with it.
What does Clerk actually cost in 2026?
Clerk's Pro plan is $25/mo with 50,000 Monthly Retained Users free; overage runs $0.02 per MRU from 50,001 to 100,000, then $0.018 up to one million, with lower rates past that, per Clerk's pricing page. At 100K MRU the bill is about $1,025/mo, around $12,300 a year , and the B2B organizations add-on puts another $100/mo on top.
Three worked scenarios on the current price sheet, before infrastructure or support tiers:
| Scenario | Arithmetic | Monthly bill |
|---|---|---|
| 40,000 MRU | inside the free allotment, Pro base only | $25 |
| 100,000 MRU | $25 + 50,000 × $0.02 | ~$1,025 |
| 100,000 MRU + organizations | $1,025 + $100 B2B add-on | ~$1,125 |
What does Clerk cost per plan in 2026?
Four plans, and the free allowance is the same on three of them:
| Plan | Base price | MRUs included | Dashboard seats |
|---|---|---|---|
| Hobby | $0 | 50,000 limit per app | up to 3 |
| Pro | $25/mo ($20 billed annually) | 50,000 included per app | up to 3 |
| Business | $300/mo ($250 billed annually) | 50,000 included per app | 10, then $20 each |
| Enterprise | custom, annual only | custom | custom |
Note the word that changes: Hobby's 50,000 is a limit, Pro's and Business's is an allowance. Cross it on Hobby and Clerk requires the upgrade; cross it on Pro and it meters. Overage runs $0.02 per MRU to 100,000, $0.018 to a million, $0.015 to ten million, $0.012 beyond.
Two lines people miss when they price this. Organizations are billed separately: 100 monthly retained organizations are included per app, and past that Clerk requires the B2B Authentication add-on at $100/mo ($85 annually) — that is a required add-on, not a per-org overage rate. And Clerk's "First Day Free" rule means a user who signs up and never returns is never billed: retention starts 24 hours after signup.
MRU is not MAU, and the difference lowers your bill
A Monthly Retained User is a user who comes back 24 hours or more after signing up; Clerk does not bill drive-by signups that bounce. Billable MRU therefore sits below raw MAU, so every calculator that reasons in MAU overstates the Clerk column. Clerk raised the free allotment from 10,000 to 50,000 MRU on 2026-02-05 and folded most of the Enhanced Authentication add-on into Pro. Before that change, 10,000 free users at $0.02 each put 100K MAU at $1,825–$2,025/mo, the origin of the $24,000-a-year gap the SERP still quotes. Get the unit and the date right: the whole decision is a delta between this bill and engineer time, and a 2× error in the bill propagates downstream.
One scope cut, made on purpose: what follows does not re-walk the official export tutorial; the Better Auth guide owns those mechanics. The money, the cutover, and the two lockout traps the guide leaves out are the rest of this page.
What does "upgrading Clerk" actually involve?
Two different jobs share the word, and only one of them is about money.
Upgrading the plan
Hobby is capped rather than metered: "Applications on the Hobby plan are limited to free tier usage. To use beyond the free tier limits, you must upgrade to the Pro plan." Cross 50,000 MRU and Clerk gives you a one-month grace period so the app keeps working while you move. Two other triggers force a plan change regardless of user count: a fourth dashboard seat requires Business, and enhanced dashboard roles beyond Owner and Viewer are Business-only.
Upgrading does not cost you the free allowance — 50,000 MRU is included on Pro and Business alike, so the bill starts at overage, not at zero. There is no traditional free trial; Clerk's stated substitute is the development instance, which is free and unlimited in features but capped at 100 users.
One trap worth naming, because it is the first search result for "clerk upgrade mid-cycle": Clerk's documentation that upgrades "take effect immediately, while downgrades take effect at the end of the current billing cycle" belongs to Clerk Billing, the feature for charging your users. It says nothing about your own workspace plan. Same for the proration language, which appears only in the seat-based-billing docs. Clerk publishes no proration rule for its own plans; the pricing page just carries "Upgrade to Pro plan" buttons.
Upgrading the SDK
The current major is Core 3, shipped 2026-03-03 as @clerk/nextjs v7 (7.7.1 as of 2026-08-08). Clerk runs a roughly six-month major cycle and keeps the previous major in long-term support for a year, so Core 2 is patched until January 2027 and the v6 line still gets releases.
Do not hand-edit the migration. Clerk ships a codemod that does AST-level transforms and catches re-exports, aliased imports and monorepo files:
npx @clerk/upgrade # package-lock.json or no lockfile
bunx @clerk/upgrade # bun.lockb / bun.lock
What Core 3 breaks in a Next.js app, in the order it will bite you: SignedIn, SignedOut and Protect collapse into a single Show component; <ClerkProvider> moves inside <body> instead of wrapping <html>; passing secretKey to clerkMiddleware() now also requires CLERK_ENCRYPTION_KEY; the Next.js floor rises to 15.2.3; and auth.protect() returns 401 rather than 404 for unauthenticated server actions. Packages were renamed too (@clerk/clerk-react to @clerk/react), and the old redirect props are gone in favour of the fallback ones.
Budget this against the migration bill above. A Core upgrade every six months is not free either — it is the recurring cost of the managed option, and it is the honest column to compare against maintaining your own auth.
What actually pushes teams off Clerk at month nine?
Under the 2026 free tier a typical month-nine product pays Clerk $0, so the real triggers are operational. Val Town left after outages that took their whole site down, a production rate limit of five requests per second across the entire account, and webhook-sync workarounds that split user data between two systems.
“Clerk went down pretty often, and went down for long periods of time... if Clerk goes down, the whole website goes down.”
Tom MacWright's Val Town writeup pairs that outage coupling with a subtler production trap: Clerk's loadUser endpoint ran fine in development, then throttled at “five requests per second. For the whole account, across all users.” If auth going down takes your product down, no free tier offsets that risk. Val Town moved sessions into their own database through a two-week dual-cookie cutover, covered below, and their verdict after the move was “so far it really has been better”: user auth no longer depends on a third party staying online.
Three operational triggers moved Val Town off Clerk: repeated outages that took the whole site down, a 5 req/s account-wide rate limit, and webhook user-sync drift.
Why can't migrated users sign in after the export?
Clerk exports password digests hashed with bcrypt; Better Auth hashes with scrypt by default. Run the export without a custom hash/verify pair and every migrated password fails verification: the user rows exist, sign-in returns invalid credentials. Configuring Better Auth to verify bcrypt digests is the fix, and the official migration guide buries it mid-tutorial.
bcrypt and scrypt are both password-hashing algorithms, and their digests are incompatible: a hash written by one cannot be verified by the other's default path. The config that prevents the lockout fits in a dozen lines:
import { betterAuth } from "better-auth";
import bcrypt from "bcrypt";
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
password: {
// Clerk exports bcrypt digests; Better Auth defaults to scrypt.
// Skip this verify pair and every migrated password fails silently:
// the user row exists, sign-in returns "invalid credentials".
hash: (password) => bcrypt.hash(password, 10),
verify: ({ hash, password }) => bcrypt.compare(password, hash),
},
},
});
The organizations gap
Clerk organizations sit outside the automated migration script; the guide's full guidance is that moving them “should be possible with additional steps” and the Organization Plugin. The teams hit hardest are the ones paying the $100/mo B2B add-on: the users most motivated to leave face the least-documented part of leaving. Budget organization and membership mapping as its own line item rather than a footnote.
The hash mismatch says nothing about which framework is better. What it decides is whether cutover day ends with a support queue full of locked-out users. ShipKit's monorepo makes the greenfield version of that decision for you: Better Auth arrives with email, OAuth, magic link and RBAC already configured, which leaves one fewer place for a month-nine surprise to hide.
How do you migrate Clerk users from development to production?
You do not. Clerk's own migration guide opens with the sentence flat: "You cannot migrate users from your Development instance to your Production instance." The instances do not share data at all, and development is capped at 100 users, so what you are really asking is how to recreate them.
The supported path is the CreateUser Backend API endpoint. Passwords survive if you send the hash rather than the plaintext: password_digest plus password_hasher, where the hasher is one of bcrypt, argon2i, argon2id, the pbkdf2 family, scrypt_firebase, scrypt_werkzeug and a dozen others. Hashers Clerk considers insecure — md5, md5_salted, sha256, sha256_salted, sha512_symfony — are transparently re-hashed to bcrypt the first time that user signs in successfully. For bulk work Clerk publishes an open-source importer, clerk/migration-tool, which takes JSON or CSV and respects the rate limits (1,000 requests per 10 seconds on a production key, 100 on a development one).
Keep the old identifiers. Clerk's recommended pattern is to store them as external_id and surface them in the session token, which is the difference between a clean cutover and a week of reconciling foreign keys.
What else fails to carry over, in the order it breaks a deploy:
- OAuth credentials. Development uses Clerk's shared credentials for most social providers. Production requires your own, per provider.
- SSO connections, Integrations and Paths. Clerk names exactly these three as excluded when you clone development settings into the new instance.
- Domain and DNS. Production needs a domain you own plus new DNS records, and propagation can take up to 48 hours. Plan the cutover around that, not the code freeze.
- Webhooks. New endpoint URL, new signing secret, created fresh in the production instance.
-
Keys.
pk_test_/sk_test_becomepk_live_/sk_live_. -
Sessions. Development uses a
__clerk_db_jwt"dev browser" object; production uses the__clientcookie. A development session means nothing in production.
There is also no staging instance: Clerk offers Development and Production only, and its documented workaround is a separate Clerk application on a separate domain — which, by the same rule, cannot share production's users either.
Notice what this exercise proves before any migration is on the table. If your users only exist inside a vendor and cannot be moved between that vendor's own environments, the export question is not hypothetical; you have already met it. That is the cheapest possible moment to decide whether you want to own the user table.
How do you cut over without logging every user out?
Better Auth's guide prices session invalidation in one sentence: “This migration will invalidate all active sessions.” Val Town answered it with a dual-cookie cutover : for two weeks every auth endpoint accepted either a Clerk session cookie or a Better Auth one, so users rolled over as they signed in.
The wrong first move is running the export against production as-is. A big-bang cutover works in the tutorial because the tutorial has no live sessions; on a nine-month-old product it forces every user to re-authenticate at once, and if the bcrypt config above is missing, a share of them cannot.
The dual-cookie cutover keeps both verification paths live behind a flag: existing Clerk sessions verify against the old path while new sign-ins issue Better Auth sessions in your own database. Rollback stays one flag-flip away until the overlap window closes, and the overlap doubles as a live test of the new session shape under real traffic. When the last Clerk cookies age out, remove the old path.
Val Town's dual-cookie cutover: a two-week overlap in which every auth endpoint accepts either session cookie, so users roll over without a forced logout.
The itemized migration bill: two engineer-weeks in real currency
Plan for about two engineer-weeks on a live product — an estimate with stated assumptions, itemized below rather than asserted. At a loaded $75/hour, 80 hours is $6,000 of engineering time. The bill splits into five workstreams; two of them are the lines every estimate misses.
Assumptions for the table: one product, Postgres already in place, hours priced at a loaded $75/hour:
| Workstream | What it covers | Estimate |
|---|---|---|
| Export and schema mapping | user export, table mapping, bcrypt digest import | 12–16 h |
| Auth config and re-testing | bcrypt verify pair, sign-in/sign-up flows, 2FA plugin | 12–16 h |
| Dual-cookie middleware | parallel session acceptance, feature flag, rollback path | 8–12 h |
| UI rebuild | replacing Clerk's prebuilt sign-in, profile and org-switcher components | 16–24 h |
| Webhook-sync teardown | removing sync endpoints, reconciling the duplicate user table | 8–16 h |
Two scenarios on the same $75/hour assumption: a product with no webhook sync and no organizations lands near the bottom of the ranges, about 56 hours ($4,200); a B2B product with both lands past the top, about 104 hours ($7,800), because the organization mapping is manual.
The line items nobody prices
Teams that followed Clerk's recommended pattern for using their own database keep user data in sync via webhooks, and leaving means unwinding two sources of truth: sync endpoints removed, the duplicate user table reconciled row by row. The recovered line is local dev: openstatus migrated partly because contributors needed an ngrok tunnel just to log in locally, and after the move auth runs offline like the rest of the stack. Payback math stays short: against a $0 Clerk bill this never pays back in cash; against $1,025/mo it pays back inside six months. Every row above is also a build-vs-buy datapoint: ShipKit sells the pre-wired version of this work for $149 one-time with unlimited projects, less than the cheapest single row of the table at the same hourly rate.
When staying on Clerk is the right call
Below 50,000 MRU your Clerk bill is $0, and $6,000 of engineering time cannot pay back against a free product. openstatus, a team that migrated off Clerk, still calls it “an amazing product — the documentation is clear, the setup straightforward.” Staying makes sense if none of the operational triggers are live.
The boundary is a trigger list rather than a calendar: if outage coupling has not bitten, the 5 req/s limit has not throttled you, and you resisted the webhook-sync pattern, Clerk is doing its job and the two engineer-weeks buy more elsewhere. Revisit when an incident lands or MRU crosses the paid tier, and take the export then, with openstatus's migration notes and the playbook above in hand.
What if the next project never books this migration?
The job at month nine is the same as at month one: reach paying customers without burning weeks on auth plumbing. The cheapest Clerk migration is the one the next project never books, and that choice happens at repo-init: ShipKit ships Better Auth pre-wired, with email, OAuth, magic link and RBAC, inside a monorepo of 14 production subsystems.
The full inventory runs from payments and admin panel to i18n, background jobs and a webhook worker, spread across 7 apps, 16 packages and 68 UI components; nine production apps have shipped on this codebase already. At $149 one-time with lifetime updates and unlimited projects, the license costs less than two hours of the migration priced above. The three paths, priced on this article's own numbers:
| Stay on Clerk | Migrate at month nine | Greenfield on ShipKit | |
|---|---|---|---|
| Upfront cost | $0 | ~$4,200–$7,800 in engineer time | $149 one-time |
| Monthly at 100K MRU | ~$1,025 | your hosting only | your hosting only |
| Sessions live in | Clerk's cloud | your database | your database |
| Auth work on day one | none | two engineer-weeks | pre-wired: email, OAuth, magic link, RBAC |
Before writing the first migration line, price the 14 subsystems against your own hourly rate: ShipKit's feature list reads as this article's pricing table with every row already built into the architecture.
Next step: Two engineer-weeks is the price of leaving Clerk late; $149 is the price of a stack where the job is already done. Price both against your own rate before the next repo-init.
FAQ
Is Better Auth production-ready in 2026 now that it joined Vercel?
Better Auth joined Vercel in July 2026 with a stated commitment to staying open source and framework-agnostic, and the project sits at 29.4k GitHub stars with 2.7k forks as of July 2026. LobeHub already documents a Clerk-to-Better-Auth path for its own self-hosters. The skeptical view exists too: one Hacker News commenter argues that delegating your database schema to an auth framework suits “throwaway projects and companies with low quality technical vision.” Weigh that thread against Val Town running Better Auth in production.
What happened to Auth.js (NextAuth)?
The Better Auth team has maintained Auth.js since September 2025, and the merger announcement recommends new projects start on Better Auth. Consolidation puts the two largest open-source JavaScript auth libraries under one roof, and it makes a 2024 Clerk-to-NextAuth migration like openstatus's the direct ancestor of today's path.
Can we migrate incrementally instead of a big-bang export?
openstatus ran a lazy migration: extend the existing users table with the new adapter fields, override getUser and createUser, and re-link OAuth accounts on next login via allowDangerousEmailAccountLinking. Users migrate as they show up. The trade-off is an overlap window longer than the two-week dual-cookie cutover, with both systems live for the duration.
Does Better Auth support 2FA and multi-tenant organizations?
Both ship as plugins, and the repository describes multi-tenant support as a first-class path. Clerk organizations still need manual mapping on the way out, because the export script does not carry them across.
Do I lose the free 50,000 users when I upgrade to Pro?
No. The 50,000 MRU allowance is included on Hobby, Pro and Business alike, so a Pro bill starts at $25 plus overage above 50,000, not at $25 plus everything. What upgrading changes is the consequence of crossing the line: on Hobby it is a hard stop with a one-month grace period, on Pro it is metered at $0.02 per MRU.
Sources
- Clerk pricing — Clerk, 2026
- New plans, more value — Clerk changelog, February 2026
- Clerk migration guide — Better Auth docs, 2026
- From Clerk to Better Auth — Val Town blog (Tom MacWright), 2026
- Migrating from Clerk to NextAuth — openstatus, 2024
- Better Auth repository — GitHub, 2026
- Auth.js joins Better Auth — Better Auth blog, 2025
- Better Auth joins Vercel — Better Auth blog, 2026
- Discussion of the Auth.js merger — Hacker News, 2025
- Clerk vs Better Auth price check (pre-repricing figures) — dev.to, 2026
- Clerk to Better Auth self-hosting migration — LobeHub docs, 2026
- Managing environments — Clerk docs, 2026
- Migrating users to Clerk — Clerk docs, 2026
- Deploying to production — Clerk docs, 2026
- CreateUser Backend API reference — Clerk docs, 2026
- Rate limits and system limits — Clerk docs, 2026
- Upgrading to Clerk Core 3 — Clerk docs, 2026
- SDK versioning and LTS policy — Clerk docs, 2026
Originally published on the ShipKit blog.


Top comments (0)