Multi-Tenant Auth & User Model — Provider Comparison
Status: Research / discussion artifact. This is intentionally not an implementation plan. The decision it informed lives in ADR-017; the implementation plan lives in 2026-04-09 WorkOS Auth Implementation.
Supersedes (in scope): 2026-03-01-user-authentication-plan.md, which proposed a roll-your-own approach (GitHub OAuth for admins + Resend magic link for clients). That plan does not address multi-tenant data model, per-tenant SSO, SCIM, Admin Portal, /t/:slug URL scoping, or the SecurityV0 super-admin switcher — all of which are explicit requirements here. Treat the older plan as an input, not the path forward.
Last updated: 2026-04-10 — added executive summary, detailed pricing deep-dive with COGS analysis, and cost optimization strategies.
Executive summary
Quick read for decision-makers. Jump to any section via the links below.
The problem
sv0-platform has no real authentication. Enterprise customers cannot be onboarded (no SAML/OIDC), our team switches tenants by editing localStorage, and there is no per-tenant configuration. This is a sales blocker.
The three viable options
| WorkOS | Clerk | Stytch B2B | |
|---|---|---|---|
| Per-customer SSO cost | $125/mo ($1,500/yr) at 1-15; $50/mo at 101-200 | $75/mo ($900/yr) at 2-15; $15/mo at 500+ | $125/mo ($1,500/yr); no published volume tiers |
| Base cost | $0 (1M MAU free) | $20-25/mo + $0.02/MRU overage | $0 (10K MAU free) + $0.10/MAU overage |
| Self-serve Admin Portal | Best-in-class | No direct equivalent | Included, embeddable |
| SCIM | First-class | Not GA (roadmap/Enterprise only) | First-class, included free |
| Time to first login | ~3-5 days | ~2-3 days | ~5-7 days |
| CISO sellability | Strong B2B brand | B2C reputation | Newer, less known |
| COGS impact at $45k ACV | 16.7% of COGS budget | 10% of COGS budget | 16.7% of COGS budget |
→ Full comparison matrix · Detailed pricing deep-dive · Cost optimization strategies
Key finding: not every client needs SSO — and free auth methods work for real clients
The $125/connection/month SSO price is not WorkOS-specific — Stytch charges identically. But that cost only applies to enterprise customers whose IT team demands IdP-level control (SAML/OIDC). Many real paying clients — especially smaller companies and channel deals — can use free auth methods:
| Auth method | Cost in WorkOS | Viable for paying clients? |
|---|---|---|
| Google OAuth ("Sign in with Google") | $0 | Yes — any client using Google Workspace |
| Microsoft OAuth | $0 | Yes — any client using Microsoft 365 |
| GitHub OAuth | $0 | Yes — developer-focused clients |
| Magic link (email OTP) | $0 | Yes — any client |
| SAML/OIDC SSO | $125/mo | Required only when client IT demands IdP control |
→ Auth method tiering deep-dive · Blended COGS model
Recommendation
WorkOS remains the recommendation for technical and operational reasons (Admin Portal, B2B data model, CISO brand). The SSO pricing concern is less severe than it initially appears because most channel clients can use free social login + domain verification. See Auth Method Tiering for the analysis and Cost Optimization Strategies for additional levers.
Related documents
| Document | Purpose |
|---|---|
| ADR-016: Multi-Tenant Auth Architecture | Vendor-independent architecture decisions |
| ADR-017: WorkOS as Auth Provider | Vendor selection decision and rationale |
| 13 — Authentication & User Management | Living architecture doc |
| WorkOS Auth Implementation Plan | Phased implementation plan |
Context
sv0-platform today has no real auth model:
- Backend (
src/api/middleware/auth.ts): JWT/JWKS scaffolding exists butREQUIRE_AUTH=falseis the default. When off, every request getsprincipalId: "dev-auth-bypass", wildcard scopes, and whateverX-Tenant-Idheader is sent. When on, it verifies a JWT against a configured JWKS endpoint — but there is no user directory to cross-check thesubclaim against. - Tenants: No
tenantscollection. Tenant is a denormalized string on every document in all 17 Mongo collections. Tenants are implicitly created on first write. No metadata, no owner, no config. - Users: No
userscollection.AuthContextis just{ principalId, method, scopes, tenantId }— built per-request, never persisted. - UI (
ui/src/context/auth-context.tsx,ui/src/pages/SettingsPage.tsx): Tenant ID + API key are entered manually into a form, stored inlocalStorageundersv0-auth, and injected into every request asx-tenant-id/x-api-key. No login page. No OTP. No magic link. No tenant list. No/t/:slugURL scoping. - Cloudflare Access:
app.securityv0.comanddev.securityv0.comsit behind CF Zero Trust, but the backend does not readCf-Access-Jwt-Assertion. CF Access is currently a network gate only. - Per-tenant config (Jira links, connector creds, feature flags): does not exist.
What the user wants:
- Real enterprise-grade auth: per-tenant IdP (SAML/OIDC), because a Fortune 500 prospect asking to install today cannot be onboarded.
- A lightweight demo path (magic link / email OTP) that we can keep for small prospects and trials.
- Per-tenant configuration surface (auth, Jira, connectors, branding).
- SecurityV0 super-admins (our team) that automatically see every tenant, with a dropdown to switch between them instead of editing localStorage.
- Shareable URLs that encode tenant + page, so two team members can paste a link and land on the same view of the same customer.
- Tenant-aware configuration that we pre-provision now but can move to self-service later.
The decision point: which auth provider (or no provider) anchors this. Everything else — data model, URL scheme, admin switcher — is downstream of that choice and is largely the same work regardless.
Evaluation criteria
Each provider is scored against what this product actually needs. Weights reflect the requirements above.
| Criterion | Why it matters for sv0 |
|---|---|
| Enterprise SSO per tenant (SAML + OIDC) | Non-negotiable for the Fortune 500 install scenario. Each customer brings their own IdP (Okta, Entra ID, Ping, Google Workspace). |
| Self-serve SSO onboarding (admin portal) | A customer IT admin must be able to set up their own SAML connection without us writing code. Otherwise every new customer is a ticket for us. |
| SCIM / directory sync | Enterprise customers want auto-provisioning and deprovisioning. Not day-1 critical but a fast follow. |
| Magic link / passwordless | For demos, POCs, and smaller customers who won't set up SSO. |
| B2B multi-tenant model built-in (Organizations, memberships, roles) | We shouldn't reinvent user↔tenant↔role tables. |
| Cross-tenant super-admin | SecurityV0 team needs to see and act on every tenant. Not all providers model this cleanly. |
| React SDK quality | UI is React + React Router v6. Less code = less risk. |
| Node/Express backend SDK | Backend is Node 24 ESM. |
| Pricing at our stage | We have ~0 paying customers today. Free tier matters. Per-MAU pricing that explodes at scale is a trap. |
| Vendor lock-in / exit cost | Migrating auth later is painful. OIDC-compliant providers are safer than ones with proprietary session models. |
| Implementation effort | Time-to-first-working-login. |
Providers considered
1. WorkOS
What it is: A B2B-focused auth platform. Started as "SSO as an API" (a drop-in SAML/OIDC broker) and has since grown into a full stack: AuthKit (hosted login UI), Organizations, SSO, Directory Sync (SCIM), Magic Auth, Admin Portal, Audit Logs. Heavily used by YC-ish B2B SaaS companies that sell into enterprise (Vercel, PlanetScale, Webflow).
Mental model:
- Organizations = tenants. You create a WorkOS Organization per customer.
- Users live in a shared directory but are members of one or more Organizations.
- Connections = a tenant's IdP config (one SAML or OIDC connection per Organization).
- Admin Portal = a magic link you generate and email to a customer IT admin; they configure their own SAML connection in a hosted UI without talking to us.
- AuthKit = a hosted login page (like Auth0's Universal Login) that handles the entire flow. Your app does an OAuth2-style redirect to AuthKit and gets back a session.
How it would work in sv0:
- Backend: add
@workos-inc/node. ReplaceverifyAndAttach()with WorkOS session verification. On first login, upsertusersandmembershipsrows keyed by WorkOSuser.id+organization.id. - Frontend: replace the Settings tenant form with a "Sign in" button that redirects to AuthKit. After callback, store the WorkOS session cookie; use the organizations the user belongs to populate the tenant switcher.
- SecurityV0 super-admin: create one WorkOS Organization called
securityv0-internal. Any user in that org (enforced by an@securityv0.comemail domain rule) gets arole: super_adminflag in our ownmembershipstable, which grants access to all tenants in the tenant switcher. - New customer onboarding: we create a WorkOS Organization + send them an Admin Portal link. They configure their Okta/Entra ID connection themselves. Done.
- Demo customers: we skip the Admin Portal and flip the Organization to "Magic Link" — user enters email, gets a one-time link.
Pros:
- Best-in-class enterprise SSO UX. Admin Portal alone saves weeks of work per customer.
- Strong B2B data model (Organizations + memberships + roles) maps 1:1 to what we need.
- SCIM/Directory Sync is first-class and uses the same Admin Portal.
- OIDC-compliant — we can migrate off if we need to.
- Well-documented, stable SDKs, used by companies at our target scale.
Cons:
- Pricing: Free up to 1M MAU for AuthKit + Magic Auth + 1M Directory Sync users, but SSO connections are $125/connection/month after the first 1M users. In practice: free until we have real paying enterprise customers, then $125/month per enterprise customer (which is trivial compared to ACV).
- Vendor has a say in your login UX if you use AuthKit's hosted page (you can self-host the form with their lower-level APIs instead).
- Super-admin cross-tenant access is not a first-class concept; we implement it on our side.
Effort: ~1 week for Phase 1 (login, sessions, tenant switcher, /t/:slug URLs, super-admin). SCIM and Admin Portal can come later without rework.
2. Clerk
What it is: A developer-experience-first auth platform. Originally B2C-focused; added Organizations in 2023 to compete in B2B. Excellent React SDK, lots of pre-built components (<SignIn />, <OrganizationSwitcher />, <UserButton />).
Mental model:
- Users are top-level.
- Organizations = tenants. Users can belong to multiple. Each membership has a role.
- Auth methods (SSO, magic link, password, OAuth social) are enabled globally, not per-organization. Enterprise SSO is per-organization via an "Enterprise Connection" add-on.
- UI components are drop-in:
<OrganizationSwitcher />would literally replace our Settings tenant form.
How it would work in sv0:
- Backend:
@clerk/backend. Middleware extractsuserIdandorgIdfrom the Clerk session cookie/JWT. We still keep our ownusers/membershipstables mirrored for queries. - Frontend: wrap the app in
<ClerkProvider>. Drop<SignIn />,<OrganizationSwitcher />,<UserButton />into the layout. UseuseOrganization()hook to get the current tenant slug. - Super-admin: Clerk doesn't model cross-org admin. We add a
role: super_adminclaim on specific Clerk users (via Clerk's public metadata) and build the cross-tenant switcher ourselves (fetch/api/admin/tenantswhensuper_admin). - Per-tenant SSO: customer IT admin clicks "Add SSO" in our UI, which opens Clerk's hosted SSO configuration flow (requires the Enterprise add-on per org).
Pros:
- Fastest time-to-first-login of any option. The React SDK is genuinely excellent.
<OrganizationSwitcher />is exactly the dropdown the user asked for, for free.- Magic link, OAuth, password, MFA — all built in.
- Free tier is generous for MAU; org add-ons are reasonable.
Cons:
- Enterprise SSO connections are $75/connection/month (2-15), tiering to $60 (16-100), $30 (101-500), $15 (500+). Cheaper per-connection than WorkOS at all tiers, but requires Pro plan ($20-25/mo) + B2B add-on ($85-100/mo) + Business plan ($250/mo for SOC 2/dashboard seats) as fixed costs.
- Clerk's session model is somewhat proprietary — migrating off is more work than WorkOS.
- Historically B2C-first; some B2B features (SCIM, advanced org roles) are newer and less battle-tested than WorkOS.
- The drop-in React components are opinionated about styling; theming to match our design system takes work.
- Cross-tenant super-admin is definitely a "build it yourself" situation.
- February 2026 pricing restructure metered enterprise connections (previously unlimited under the Enhanced Authentication add-on). Orgs with 3+ connections see increased costs vs. the old model.
- SOC 2 artifacts now require the Business plan ($250/mo) — potentially needed for enterprise sales.
Effort: ~3-5 days for Phase 1 (thanks to pre-built components). SCIM is newer; verify it before committing.
Pricing sources: clerk.com/pricing, Feb 2026 plan changes, SuperTokens Clerk pricing analysis.
3. Stytch B2B
What it is: Stytch's B2B-specific product. Stytch started as passwordless auth and added a B2B suite in 2023 with Organizations, SSO, SCIM, and RBAC. API-first — they explicitly de-emphasize hosted UI in favor of giving you headless primitives.
Mental model:
- Very similar to WorkOS: Organizations = tenants, Members = users within an org, Connected Apps = IdPs.
- Every auth method (magic link, SSO, password, OAuth) can be enabled/disabled per Organization. This is more granular than WorkOS or Clerk.
- No hosted login UI by default — you call their API and build the UI yourself. There's an optional prebuilt UI kit.
How it would work in sv0:
- Backend:
stytchNode SDK. Custom middleware that callsstytch.sessions.authenticate()on every request, maps to ourusers/membershipstables. - Frontend: build our own login form that calls
stytch.magicLinks.email.loginOrCreate(). For SSO, callstytch.sso.start(). This is more code than Clerk or WorkOS AuthKit. - Per-org auth method config: Stytch lets us toggle "this org requires SSO", "this org allows magic link only" via their dashboard or API — cleaner than WorkOS.
- Super-admin: similar to others — we build it on our side.
Pros:
- The most granular per-organization auth config of the three managed options. Good for "demo tenants use magic link, enterprise tenants require SAML".
- Free tier includes 5 SSO/SCIM connections — covers the pilot phase at zero cost.
- API-first approach means minimal vendor lock-in on the UI layer.
- Unlimited organizations at all tiers.
Cons:
- SSO connections beyond 5 cost $125/connection/month — identical to WorkOS, with no published volume tiers. This is the critical finding: Stytch is not cheaper than WorkOS at scale.
- MAU overage is $0.10/MAU — 5-8x higher than Clerk's $0.02/MRU. Not a concern at sv0's ~30 users/customer scale, but a trap if usage patterns change.
- More code to write than Clerk (no drop-in components) or WorkOS (no AuthKit hosted flow).
- Smaller ecosystem than WorkOS/Clerk — fewer blog posts, smaller Discord, less inertia.
- Has an embeddable Admin Portal (updated finding) — customers can self-serve SSO/SCIM config, MFA policies, and role mapping. Less known than WorkOS's but functionally capable.
- SCIM is included free (5 connections in free tier, shared pool with SSO). GA and supports Okta, Azure AD, OneLogin with real-time webhooks. Stronger than Clerk on this axis.
- Pro plan ($249/mo) and Scale plan ($799/mo) include only 3 and 8 connections respectively — poor value vs WorkOS AuthKit which is free.
Effort: ~1-1.5 weeks for Phase 1. Main cost is building the login UI ourselves.
Pricing sources: stytch.com/pricing, SuperTokens Stytch pricing analysis.
4. Auth0 (Okta)
What it is: The legacy leader. Acquired by Okta in 2021. Supports everything. Used by enterprises everywhere.
Mental model:
- Tenants in Auth0 terminology mean "instances of Auth0", not customer tenants — this is confusing. What we call a tenant is an Organization in Auth0 (added in 2021 to catch up with B2B).
- Universal Login (hosted) handles the flow. Rules/Actions hook into the login pipeline for custom logic.
- Enterprise Connections per Organization for SAML/OIDC.
How it would work in sv0:
- Mechanically similar to WorkOS: Organizations map to tenants, users map to members, Universal Login handles the redirect flow. Backend verifies Auth0 JWTs (our existing JWKS middleware almost works out of the box).
Pros:
- Everyone on the enterprise side recognizes the name — zero resistance in security reviews.
- Feature-complete. Literally every feature any other provider has, Auth0 has.
- Our existing JWT/JWKS middleware is closest to usable with Auth0 (least backend refactor).
Cons:
- Pricing is brutal for B2B SaaS. Enterprise plan with Organizations starts around $240/month and scales aggressively with MAU. Not viable pre-revenue.
- The dashboard and DX are dated compared to WorkOS/Clerk.
- "Organizations" was bolted on in 2021 and still shows — feels like a second-class citizen.
- Migrating off Auth0 is hard (Rules, custom claims, custom DB connections, Auth0-specific quirks).
Effort: ~1 week backend, similar to WorkOS. But the pricing makes it a non-starter unless we already sell to a customer that mandates Auth0.
5. Cloudflare Access (Zero Trust) — extend what we have
What it is: A network-layer identity gateway. Already sits in front of app.securityv0.com and dev.securityv0.com. Handles Google Workspace, GitHub, SAML, OIDC, Okta, Entra ID via Cloudflare's IdP integrations. Injects a signed Cf-Access-Jwt-Assertion header into requests reaching the origin.
Mental model:
- CF Access policies are configured in the Cloudflare dashboard, not in app code. Policies are tied to hostnames and paths.
- Every authenticated request gets a CF Access JWT that contains the user's email and identity provider.
- No concept of "Organization" — CF Access doesn't know what a tenant is.
How it would work in sv0:
- Backend: add a middleware that verifies
Cf-Access-Jwt-Assertionagainst CF's JWKS (well-documented), extractsemailandidentity_nonce, and maps that to our ownuserstable. - Tenant model: 100% our problem. CF doesn't help. We still build
tenants,memberships, tenant switcher,/t/:slugURLs, per-tenant config. - Per-tenant SSO: we'd create a CF Access "application" per tenant (one per subdomain or one per path pattern). Customer IdPs are configured in the CF dashboard by us, not the customer. This is the dealbreaker for self-service.
- Magic link: CF Access has a "One-time PIN" email method. Works fine for demos.
- Super-admin: we mark specific emails (e.g.
@securityv0.comGoogle Workspace) as super-admin in ourmembershipstable.
Pros:
- Free for up to 50 users, then $3/user/month. Cheaper than everything else by an order of magnitude.
- Already in place. We'd literally be connecting the dots, not adding a vendor.
- No vendor lock-in beyond CF itself (which we already depend on).
- Works for local dev with CF
cloudflaredif we want, or we just skip it locally withREQUIRE_AUTH=false.
Cons:
- No self-service SSO onboarding. Every enterprise customer that wants to bring their Okta/Entra ID requires us to log into the CF dashboard and configure it. This scales to maybe 20 customers before it hurts. It is the single biggest argument against this option.
- CF Access is fundamentally a hostname-scoped gateway. Multi-tenant URL patterns like
/t/:slugwork, but per-tenant SSO policies are cleaner with subdomains, which means wildcard TLS and wildcard CF apps — not free work. - No Organization/membership primitives. We build all of that.
- Local dev story is awkward: CF Access doesn't run locally, so
REQUIRE_AUTH=falsestays the local dev story, and we'd diverge further between local and prod auth. - Audit logs and user management live in the CF dashboard, not in our app.
Effort: ~3-4 days for Phase 1 (it's mostly on our side: tenants table, memberships, switcher, /t/:slug, super-admin). But the self-service ceiling makes this a phase-1-only answer, not a long-term one.
6. Roll our own OIDC (openid-client + Mongo)
What it is: Use the openid-client npm package to implement an OIDC relying party ourselves. Store users, tenants, memberships, and per-tenant OIDC configs in Mongo. Implement magic link by generating a signed token, emailing it via Resend/Postmark, and verifying on click.
How it would work in sv0:
- Backend: add
openid-client,iron-session(orexpress-session), a mail transport. Build/auth/login,/auth/callback,/auth/logout,/auth/magic-link/request,/auth/magic-link/verify. Store per-tenant OIDC config in atenant_auth_configscollection. - Frontend: build the login page, tenant-scoped callback handling, session hooks, the org switcher, the admin SSO config UI, the email templates.
- SCIM: we'd have to implement it. SCIM is a 400-page RFC. This alone is weeks of work.
- Magic link delivery: we own deliverability, bounces, rate limits, token rotation.
- Super-admin: easy — just a flag in our DB.
Pros:
- Zero vendor cost.
- Zero lock-in. It's just OIDC.
- Complete control over the UX, data model, and session lifecycle.
- Every feature is exactly as much or as little as we need.
Cons:
- We become an auth company. Session rotation, CSRF, PKCE, nonce replay, clock skew, JWKS caching, SAML (if any customer wants it — SAML is not OIDC and
openid-clientwon't help), SCIM, MFA, passkeys, password reset flows, account lockout, email deliverability, audit logs, admin portal, brute-force protection… this never ends. - Security risk surface is enormous. Every one of those items is a place to have a CVE.
- Opportunity cost: the weeks spent on auth are weeks not spent on the actual product.
- SAML support means adding
@node-saml/node-samland dealing with XML signing, which is even more painful than OIDC.
Effort: 2-3 weeks for a minimal Phase 1, probably 6-8 weeks to reach parity with what WorkOS gives us out of the box. Ongoing maintenance forever.
Side-by-side comparison
| Criterion | WorkOS | Clerk | Stytch B2B | Auth0 | CF Access | Roll own |
|---|---|---|---|---|---|---|
| Enterprise SSO (SAML+OIDC) per tenant | ★★★★★ | ★★★★ | ★★★★ | ★★★★★ | ★★ (manual) | ★ (huge work) |
| Self-serve SSO onboarding (Admin Portal) | ★★★★★ | ★★ (no equivalent) | ★★★★ (embeddable) | ★★★ | ✗ | ✗ |
| SCIM / directory sync | ★★★★★ | ★★ (not GA) | ★★★★ (included free) | ★★★★ | ✗ | ✗ |
| Magic link / passwordless | ★★★★ | ★★★★★ | ★★★★★ | ★★★★ | ★★★ | ★★ (build it) |
| B2B data model (orgs/memberships) | ★★★★★ | ★★★★ | ★★★★★ | ★★★ (bolted on) | ✗ | You build it |
| React SDK quality | ★★★★ | ★★★★★ | ★★★ | ★★★ | n/a | n/a |
| Cross-tenant super-admin | DIY | DIY | DIY | DIY | DIY | DIY |
| Pricing at 0-10 SSO customers | Free (AuthKit) + $125/SSO | $20/mo base + $75/SSO | Free (5 SSO included) | ~$240/mo + SSO | $0-$3/user | $0 + 6wk eng |
| Pricing at 50 SSO customers | ~$5k/mo ($100/SSO tier 2) | ~$3.3k/mo ($60/SSO + base) | ~$5.6k/mo ($125/SSO, no tier) | $$$$ | ~$300/mo but ceiling reached | $0 + ongoing eng |
| Pricing at 200 SSO customers | ~$10k/mo ($50/SSO tier 4) | ~$3.4k/mo ($15/SSO + base) | No published volume tier | $$$$ | Not viable | $0 + ongoing eng |
| SSO cost per customer at $45k ACV | 16.7%→6.7% of COGS | 10%→2.2% of COGS | 16.7% of COGS (flat) | N/A | $0 but manual | $0 but liability |
| Vendor lock-in | Low (OIDC) | Medium | Low | High | Low | None |
| Time to first login | 3-5 days | 2-3 days | 5-7 days | 5-7 days | 3-4 days | 2-3 weeks |
| Sellability to CISOs | ★★★★ ("we use WorkOS") | ★★★ | ★★★ | ★★★★★ | ★★★★ ("CF Zero Trust") | ★★ ("we built it") |
Recommendation: WorkOS (with active pricing management)
For a B2B security product selling to Fortune 500 CISOs, WorkOS is the right answer on technical and operational merits. However, the per-connection SSO cost requires active management — it is not a rounding error at $45k channel ACV. Reasoning:
- The Admin Portal is the decisive feature. Every other option forces us into a support ticket per SSO setup. WorkOS lets a customer's IT admin configure their own SAML in a 5-minute self-serve flow. At the scale we want to reach, this is the difference between auth being a non-issue and auth being a bottleneck.
- B2B data model is native, not bolted on. Organizations, Members, Connections, Directory Sync all map cleanly to
tenants,users,memberships,tenant_auth_configson our side. - Free until real revenue. AuthKit and Magic Auth are free up to 1M MAU. SSO costs only start when enterprise contracts do.
- OIDC-compliant, low lock-in. If we ever need to leave (including for cost reasons), we can.
- CISO-friendly positioning. "We use WorkOS" is known in the security buyer community and won't raise eyebrows.
- The piece it doesn't solve — cross-tenant super-admin, per-tenant app config (Jira etc),
/t/:slugURLs, shareable links — we have to build anyway, and that work is the same regardless of provider.
Pricing concern: At $45k channel ACV with 20% COGS target, SSO at $125/connection/month ($1,500/yr) consumes 16.7% of the COGS budget. This is not sustainable at scale without mitigation. See Cost Optimization Strategies — the highest-leverage action is a 15-minute WorkOS sales call about the startup program and volume commits.
Key insight from the deep-dive: the $125/connection price is industry-standard, not WorkOS-specific. Stytch charges the same. The only provider that is materially cheaper at scale is Clerk ($75→$15 tiering), but Clerk trades off Admin Portal maturity, session model portability, and CISO brand recognition.
Decision tree:
- If WorkOS startup program or volume negotiation reduces SSO to ≤$75/connection: → WorkOS. Problem solved.
- If WorkOS won't negotiate and we project 50+ enterprise customers within 18 months: → Switch to Clerk. Accept weaker Admin Portal; cost savings justify the ops delta.
- If we want zero per-connection cost and have engineering bandwidth: → WorkOS for AuthKit (free) + BoxyHQ Jackson for SAML brokering ($0 self-hosted). Best COGS but most implementation work.
- If budget is the overriding constraint today: → Cloudflare Access for phase 1 with a clear plan to migrate to WorkOS or Clerk when the first enterprise customer asks for Okta. Migration is viable because our
users/membershipstables are provider-independent by design (ADR-016).
Immediate next step: Make the WorkOS sales call before committing to implementation.
Pricing deep-dive and COGS analysis
Updated 2026-04-10 with live pricing from all three viable providers and sv0's actual go-to-market numbers.
sv0 pricing context
| Channel | ACV | 20% COGS target | Auth budget (if 15% of COGS) |
|---|---|---|---|
| Partner (channel) | $45,000/yr | $9,000/yr | $1,350/yr |
| Direct (mid) | $60,000/yr | $12,000/yr | $1,800/yr |
| Direct (high) | $90,000/yr | $18,000/yr | $2,700/yr |
Sergey's constraint: 20% COGS inclusive of cloud, support, and all software licenses. Having 15%+ of that consumed by SSO alone is a scaling problem.
Detailed pricing breakdown per provider
WorkOS (current pricing as of April 2026)
| Item | Cost | Notes |
|---|---|---|
| AuthKit (hosted login) | Free up to 1M MAU | Effectively $0 forever for sv0 (~30 users/customer × hundreds of customers ≪ 1M) |
| SSO connections (1-15) | $125/connection/month ($1,500/yr) | One connection per enterprise customer with SAML/OIDC |
| SSO connections (16-50) | $100/connection/month ($1,200/yr) | Volume tier 2 |
| SSO connections (51-100) | $75/connection/month ($900/yr) | Volume tier 3 |
| SSO connections (101-200) | $50/connection/month ($600/yr) | Volume tier 4 |
| Directory Sync (SCIM) | Same tiered pricing as SSO | Optional, per customer |
| Admin Portal | Included free | Self-serve SAML config for customer IT admins |
| Magic Auth (magic link) | Included free in AuthKit | $0 for eval/demo customers |
| M2M Applications | Included | No per-app fee documented |
| API Keys widget | Included | No per-key fee documented |
| Startup program | Unconfirmed — requires sales call | Potentially waives connection fees for 12 months |
WorkOS per-customer cost at sv0 scale:
| Scenario | SSO customers | Tier | Annual cost per customer | Total annual | % of COGS ($45k ACV) |
|---|---|---|---|---|---|
| Early (1-15 customers) | 1-15 | $125/mo | $1,500 | $1,500-$22,500 | 16.7% |
| Growth (16-50) | 30 | $100/mo | $1,200 | $36,000 | 13.3% |
| Scale (51-100) | 75 | $75/mo | $900 | $67,500 | 10.0% |
| Mature (101-200) | 150 | $50/mo | $600 | $90,000 | 6.7% |
Clerk (pricing as of Feb 2026 restructuring)
| Item | Cost | Notes |
|---|---|---|
| Base plan (Pro) | $20/mo (annual) or $25/mo (monthly) | Required for enterprise features |
| MRU (monthly retained users) | 50,000 free; $0.02/MRU overage | sv0 with 30 users × 50 customers = 1,500 MRU → $0 |
| B2B add-on (Enhanced) | $85/mo (annual) or $100/mo | Includes unlimited org members, domain restrictions, custom roles |
| Enterprise connections (2-15) | $75/connection/month ($900/yr) | Per SAML/OIDC connection. 1 included in Pro. |
| Enterprise connections (16-100) | $60/connection/month ($720/yr) | Volume tier 2 |
| Enterprise connections (101-500) | $30/connection/month ($360/yr) | Volume tier 3 |
| Enterprise connections (500+) | $15/connection/month ($180/yr) | Volume tier 4 |
| Organizations | 100 free; $1/MAO overage | One org per customer tenant |
| Dashboard seats (4+) | Requires Business plan ($250/mo) | Relevant for SecurityV0 team |
| SOC 2 artifacts | Requires Business plan ($250/mo) | May be needed for enterprise sales |
| SCIM / Directory Sync | Part of Enterprise tier or B2B add-on | Less mature than WorkOS |
| Admin Portal equivalent | Exists, less battle-tested | Not as polished as WorkOS |
| Startup programs | YC, Stripe Atlas, OnDeck — up to 1yr discounts | Requires application |
Clerk per-customer cost at sv0 scale (assumes Pro + B2B add-on + Business plan for SOC 2):
| Scenario | SSO customers | Connection tier | Annual SSO cost/customer | Fixed annual | Total annual | % of COGS ($45k ACV) |
|---|---|---|---|---|---|---|
| Early (1-15) | 10 | $75/mo | $900 | ~$4,260 (Pro+B2B+Biz) | $13,260 | 10.0% per customer |
| Growth (16-100) | 50 | $60/mo | $720 | ~$4,260 | $40,260 | 8.0% |
| Scale (101-500) | 200 | $30/mo | $360 | ~$4,260 | $76,260 | 4.0% |
| Mature (500+) | 500 | $15/mo | $180 | ~$4,260 | $94,260 | 2.0% |
Note: Fixed costs (Pro $240/yr + B2B $1,020/yr + Business $3,000/yr) amortize across customers.
Stytch B2B (current pricing)
| Item | Cost | Notes |
|---|---|---|
| Free tier | 10,000 MAU + 5 SSO/SCIM connections + 1,000 M2M tokens | Good for pilot |
| MAU overage | $0.10/MAU beyond 10,000 | sv0: ~1,500 MAU → $0. At 50 customers × 30 users = still under 10K |
| Additional SSO connections | $125/connection/month ($1,500/yr) | Same price as WorkOS — no improvement |
| Pro plan | $249/month ($2,988/yr) | Includes 3 SSO connections |
| Scale plan | $799/month ($9,588/yr) | Includes 8 SSO connections |
| AWS Marketplace annual | $25,000/yr | Includes 10K MAU + 5 SSO connections + overages |
| Branding removal | $99/mo | Optional |
| SCIM | Included in SSO connection pricing | Same $125/connection |
| Admin Portal equivalent | Exists, less mature | More setup work per customer |
| M2M tokens | 1,000 free; $0.005/token overage | Relevant for bot access |
Stytch per-customer cost at sv0 scale:
| Scenario | SSO customers | Annual cost/customer | Fixed annual | Total annual | % of COGS ($45k ACV) |
|---|---|---|---|---|---|
| Early (1-5) | 5 | $0 (free tier) | $0 | $0 | 0% |
| Early (6-15) | 10 | $1,500 (5 overage) | $0 | $7,500 | 16.7% |
| Growth w/ Pro plan | 20 | ~$1,275* | $2,988 | $25,500 | 14.2% |
| Growth w/ Scale plan | 40 | ~$1,200* | $9,588 | $48,000 | 13.3% |
Pro/Scale include some connections, reducing marginal cost slightly. No published volume tiers beyond included connections.
Head-to-head SSO cost comparison
The metric that matters: annual cost per enterprise customer for SSO, at different scales.
| Enterprise customers | WorkOS | Clerk | Stytch |
|---|---|---|---|
| 1 | $1,500 | $900 + base costs | $0 (free tier) |
| 5 | $1,500 each | $900 each + ~$4.3k fixed | $0 (free tier covers 5) |
| 10 | $1,500 each | $900 each + ~$4.3k fixed | $1,500 each (beyond free 5) |
| 15 | $1,500 each | $900 each → $720 at 16th | $1,500 each |
| 50 | $1,200 each (tier 2) | $720 each (tier 2) | $1,500 each (no tiers) |
| 100 | $900 each (tier 3) | $360 each (tier 3) | $1,500 each (no tiers) |
| 200 | $600 each (tier 4) | $180 each (tier 4) | No published volume discount |
Key finding: Stytch is only cheaper if you have ≤5 SSO customers (free tier). Beyond that, it's the same price as WorkOS ($125/connection) with no published volume tiers. Clerk is consistently cheaper per-connection and has the best volume curve, but has higher fixed costs and less mature B2B features.
COGS impact summary at $45k channel ACV
| Scale | WorkOS annual | Clerk annual* | Stytch annual | COGS budget ($9k/customer) |
|---|---|---|---|---|
| Per customer (early) | $1,500 (16.7%) | ~$1,330 (14.8%) | $1,500 (16.7%) | $9,000 |
| Per customer (50 customers) | $1,200 (13.3%) | ~$805 (8.9%) | $1,500 (16.7%) | $9,000 |
| Per customer (100 customers) | $900 (10.0%) | ~$403 (4.5%) | $1,500 (16.7%) | $9,000 |
| Per customer (200 customers) | $600 (6.7%) | ~$201 (2.2%) | $1,500 (16.7%) | $9,000 |
Clerk: includes amortized fixed costs (Pro + B2B + Business plans).
At $60k direct ACV (COGS budget = $12k), all percentages drop by ~25%. At $90k direct ACV, by ~50%.
Auth method tiering: which clients need SSO?
Updated 2026-04-10. Not every paying customer requires a $125/mo SAML SSO connection. WorkOS AuthKit includes several free authentication methods that are fully production-ready for real clients.
Free auth methods available in WorkOS AuthKit
| Method | How it works | Cost | Auto-org-join? |
|---|---|---|---|
| Google OAuth | "Sign in with Google" button. Works for any Google Workspace or personal Google account. | $0 | No — requires invitation or our domain-match code |
| Microsoft OAuth | "Sign in with Microsoft" button. Works for any Microsoft 365 or personal account. | $0 | No — same as Google |
| GitHub OAuth | "Sign in with GitHub". Good for developer-focused clients. | $0 | No — same |
| Magic link | User enters email, gets a one-time link. | $0 | No — invitation-based |
| Email + password | Traditional signup with email verification. | $0 | No — invitation-based |
All of these are included free in AuthKit up to 1M MAU. They are not limited to demos or evaluations — they are production-ready for paying clients.
The gap: automatic Organization membership with social login
When a user signs in via Google social login with user@acme.com, WorkOS does not automatically add them to the "Acme" Organization — even if acme.com is a verified domain on that org. Domain-based auto-join in WorkOS only triggers during SSO flows (SAML/OIDC connections).
For social-login clients, there are two approaches:
Option A: Invitation-based (zero custom code)
- Super-admin provisions the "Acme" tenant and verifies
acme.comas a domain - Super-admin invites
ciso@acme.comvia WorkOS → user gets email → clicks "Sign in with Google" → lands in the Acme org - Acme admins can invite additional teammates through an "Invite" feature in the UI
- Suitable for most small-to-mid clients
Option B: Domain-match auto-join (small custom code, ~20 lines)
- When a user signs in via social login, our
membershipMiddlewarechecks if their email domain matches a verified domain on any tenant - If yes → auto-create a membership row → user is immediately in the right org
- This gives the same "just sign in and you're in" experience as SSO, without the $125/mo connection
- Requires a domain verification step (DNS TXT record or manual approval) to prevent spoofing
What neither option provides (and only SAML SSO does):
- Customer IT admin enforcing login exclusively through their corporate IdP
- Conditional access policies (require specific IP ranges, MFA, device compliance) from the customer's IdP
- SCIM auto-provisioning (automatically add/remove users when Okta/Entra ID directory changes)
- Centralized audit trail in the customer's own IdP dashboard
Which clients actually need SAML SSO?
| Client profile | Typical auth need | Why? |
|---|---|---|
| Small company (10-200 employees) on Google Workspace | Google OAuth + invitation | IT team doesn't enforce IdP-only login. "Sign in with Google" is natural. |
| Small company on Microsoft 365 | Microsoft OAuth + invitation | Same — "Sign in with Microsoft" works. |
| Developer-focused team | GitHub OAuth | Natural fit for security/devops buyers. |
| Mid-market (200-2000) without strict IT policy | Social login + domain-match auto-join | Good enough. IT team doesn't mandate SAML. |
| Mid-market with IT security mandate | SAML SSO | IT policy requires all business tools go through Okta/Entra ID. Non-negotiable. |
| Enterprise (2000+) / regulated industry | SAML SSO + SCIM | Always. This is a procurement checkbox. |
| Government / financial / healthcare | SAML SSO + SCIM + MFA enforcement | Always. Compliance frameworks (FedRAMP, SOX, HIPAA) require it. |
SSO adoption sensitivity analysis
We don't know what percentage of clients will require SAML SSO versus free auth. Rather than guess, the table below shows the COGS math across four adoption scenarios. Pick the row that matches your gut, or interpolate.
Assumptions: SSO = $1,500/yr (WorkOS list price, no volume discount). Non-SSO = $0. COGS budget = 20% of ACV.
| SSO adoption rate | Partner ($45k ACV, $9k COGS) | Direct mid ($60k, $12k COGS) | Direct high ($90k, $18k COGS) |
|---|---|---|---|
| 35% (optimistic) | $525/customer → 5.8% of COGS | $525 → 4.4% | $525 → 2.9% |
| 50% (moderate) | $750/customer → 8.3% of COGS | $750 → 6.3% | $750 → 4.2% |
| 70% (conservative) | $1,050/customer → 11.7% of COGS | $1,050 → 8.8% | $1,050 → 5.8% |
| 100% (worst case) | $1,500/customer → 16.7% of COGS | $1,500 → 12.5% | $1,500 → 8.3% |
Reading the table: Even at the conservative 70% scenario, the partner-channel COGS is 11.7% — a concern but manageable with volume discounts (drops to $600/yr at WorkOS tier 4). At 50% or below, SSO COGS is under 10% across all channels. The worst-case 16.7% only materializes if literally every $45k partner client demands SAML — unlikely given the client profiles above.
With volume tier discounts (WorkOS drops to $50/connection at 101+), the cost improves further at scale. Assumes 40% SSO adoption for illustration:
| Scale (all channels, 40% SSO) | SSO customers | Non-SSO customers | Blended annual auth/customer | Blended COGS % ($45k ACV) |
|---|---|---|---|---|
| 50 total (20 SSO) | 20 × $1,200/yr (tier 2) | 30 × $0 | $480 | 5.3% |
| 100 total (40 SSO) | 40 × $900/yr (tier 3) | 60 × $0 | $360 | 4.0% |
| 200 total (80 SSO) | 80 × $600/yr (tier 4) | 120 × $0 | $240 | 2.7% |
Implementation note
The domain-match auto-join code (Option B above) should be included in the Phase 1 implementation plan. It's ~20 lines in membershipMiddleware:
on social-login callback:
email_domain := extract_domain(authContext.user.email)
matching_tenant := db.tenants.findOne({ verified_domains: email_domain })
if matching_tenant AND NOT existing_membership(user, matching_tenant):
db.memberships.insert({ user_id, tenant_id: matching_tenant._id, role: "member" })
This also requires adding a verified_domains: string[] field to the TenantDoc type and a small admin UI for domain verification (DNS TXT record check or manual super-admin approval).
Cost optimization strategies
Regardless of provider, there are concrete ways to reduce the per-customer auth COGS.
Strategy 1: Negotiate volume commitments
All three providers offer custom enterprise pricing. Concrete levers:
- WorkOS startup program — unconfirmed terms but reportedly waives connection fees for 12 months. A 15-minute sales call is the highest-ROI action on this list.
- Annual volume commit — committing to X connections/year unlocks lower per-connection rates. WorkOS tier 4 ($50/connection) is normally at 101+, but a commitment may unlock it earlier.
- Clerk startup program — YC/Stripe Atlas partners get pre-negotiated discounts for up to 1 year. We qualify via Y Combinator or Stripe Atlas if applicable.
- Stytch AWS Marketplace — $25k/yr flat rate includes 5 SSO connections + base features. Economical if we have exactly 5-8 enterprise customers.
Strategy 2: Defer SSO to contract signing (already planned)
SSO is only enabled when a paid enterprise contract is signed. Evaluations, POCs, and demos use free magic link. This means:
- The first $125/mo hits the books the same day the first enterprise contract does.
- 80%+ of active tenants may never need SSO (small teams, trials, internal).
- The WorkOS bill scales 1:1 with enterprise revenue events, not with tenant count.
Strategy 3: Bundle SSO into the enterprise tier
If SSO costs $1,500/yr per customer, make it a line item in the enterprise pricing:
- $45k channel ACV → SSO is "included" but the price already accounts for it (3.3% of ACV).
- $60k+ direct ACV → SSO cost is 2.5% of ACV, well within normal software COGS.
- Alternative: offer a "Standard" tier without SSO (magic link + password) at $30k ACV, and an "Enterprise" tier with SSO at $45k+. The $15k delta more than covers the $1,500 SSO cost.
Strategy 4: Open-source SAML proxy (hybrid approach)
Use WorkOS for everything except SSO brokering. Use an open-source SAML proxy for the actual IdP connections:
| Option | What it is | Cost | Trade-off |
|---|---|---|---|
| BoxyHQ SAML Jackson | OSS SAML/OIDC proxy, self-hosted | $0 (self-hosted) or $49/mo (cloud) | We run infra, no Admin Portal, more ops per customer |
| SSOJet | SSO-as-a-service, self-hosted option | From $49/mo | Lighter than WorkOS/Clerk for SSO-only |
| Osso | OSS SAML admin | $0 (self-hosted) | Less maintained, Ruby-based |
Hybrid architecture: WorkOS for AuthKit (login, sessions, magic link, user management — free), BoxyHQ Jackson for SAML/OIDC brokering ($0 self-hosted). We'd lose WorkOS Admin Portal (customers configure SAML via our own UI or Jackson's admin), but eliminate the $125/connection cost entirely.
Trade-off: More engineering time (Jackson setup, SAML config UI), more ops burden (we host and maintain the proxy), less polished customer experience (no WorkOS Admin Portal). Estimated: 2-3 weeks additional implementation + ongoing maintenance. At 50 enterprise customers, this saves ~$75k/yr vs WorkOS but costs us a full-time week of ops per quarter.
Strategy 5: Switch to Clerk if volume is the priority
Clerk's aggressive volume tiers make it the cheapest at scale:
- At 100 customers: $360/yr per customer vs WorkOS $900/yr → saves $54k/yr
- At 200 customers: $180/yr per customer vs WorkOS $600/yr → saves $84k/yr
The trade-off is a weaker Admin Portal (more ops per onboarding) and a more proprietary session model (harder exit). If onboarding velocity matters less than COGS, Clerk wins on pure cost.
Strategy 6: Negotiate SSO into customer contracts
Enterprise customers often have their own SSO budgets. Frame it as: "SSO integration is available as part of the Enterprise tier at $X" — passing the cost through rather than absorbing it. Common in B2B SaaS where per-tenant SSO is an explicit feature, not a default.
Recommended action plan
- Immediate: Call WorkOS sales. Ask about startup program, volume commit pricing for 10-20 connections, and whether they can match Clerk's tier 3+ rates. This is 15 minutes of work with potentially $50k+/yr savings at scale.
- If WorkOS negotiation succeeds: Proceed with WorkOS per current plan. The combination of Admin Portal + negotiated rates + deferred SSO activation makes the COGS math work.
- If WorkOS negotiation fails and we project 50+ enterprise customers within 18 months: Switch recommendation to Clerk. Accept the weaker Admin Portal; the cost savings justify the extra ops.
- If we want zero per-connection cost: Evaluate BoxyHQ Jackson hybrid. Only viable if we have engineering bandwidth for the proxy setup and are willing to build our own SAML config UI.
Note: The open questions that were previously in this section have been resolved. Provider choice, phasing, admin identity source, local dev story, and per-tenant config scope are all addressed in ADR-017 and the implementation plan.