SHOTid auditfeat/v2 · 38549fa · 2026-05-16
Cost · §09

Cost economics & vendor lock-in

Branchfeat/v2 Commit38549fa AudienceJonny, Liam, eng
01

Today — the £/month at v0

Before a single Sport Head registers, what is the bill? Mostly zero, but with a couple of footguns hiding in the "free" column.

The current stack runs almost entirely on free tiers. That is deliberate and sensible for pre-launch. The risk is not the bill today — it is that several free tiers have operational limits (build minutes, deploys per day, request-per-day caps) that bite well before any cost limit does.

LineTier todayFree ceiling (2026)£/mo at v0
Cloudflare Pages (sporthead-id, sporthead-com)Free500 builds/mo, unlimited bandwidth, 100 custom domains/project£0
Cloudflare Workers (reserve, federation-router)Free100k req/day, 10ms CPU/req£0
Cloudflare D1 (reserve worker)Free5GB storage, 5M rows read/day, 100k writes/day£0
Cloudflare KV (federation theme cache)Free100k reads/day, 1k writes/day, 1GB£0
Cloudflare TurnstileFree1M widget calls/mo£0
Supabase (sporthead-id project)Free500MB DB, 1GB Storage, 2GB egress, 50k MAU, pauses after 7d inactivity£0
GitHub ActionsFree (public) / 2000 min on private2000 min/mo private repos£0
GitHub Packages (planned, private)2GB storage, 1GB bandwidth/mo on free£0
Domain registrations (sporthead.id, .com, federation vanity)~£8

Bottom line: ~£8/mo, dominated by domain renewals. Two non-obvious traps: (1) Supabase free-tier projects pause after 7 days of no API activity — fine for dev, fatal the day a federation partner pokes at a portal you forgot existed; (2) GitHub Packages private bandwidth is metered the moment a consumer (SHOTclubhouse repo, CI, contractor laptop) starts pulling tagged versions of @sporthead/identity. Flip Supabase to Pro and GitHub to paid before launch, not after the first incident.

02

Bill curves at 5k / 50k / 500k Sport Heads

Where do the curves bend? Per-Sport-Head per month: ~5 sign-ins, 20 page views, 30 RPCs, 10 trait fetches, 1 avatar render. Two federations (SLFA + WAB) at 50k combined members, scaling proportionally.

Line5k (launch)50k (year 1)500k (year 2-3)
Supabase tierPro $25Pro $25 + ~$10 compute + ~$15 egress overageTeam $599 floor, likely Enterprise — model £3-6k/mo
Supabase MAU billingwithin Pro 100k MAUwithin Pro 100k MAU500k MAU × $0.00325 over 100k = ~$1,300 above tier
Cloudflare Workers req~5M/mo — free~50M/mo — Paid $5 base + $0.30/M over 10M = ~$17~500M/mo — ~$155
Cloudflare D1 (reserve + audit logs)Free~$2-5 reads, ~$1 writes~$30-60
Cloudflare KV (theme lookup)FreeFree at ~10M readsPaid $5 + $0.50/M reads over 10M = ~$25
Trait PNG bandwidth (CF Pages or R2)Negligible~150GB egress, CF free~1.5TB/mo through CF — still free if from Pages/R2, not Workers
VC issuance storage (Supabase or R2)~5k blobs ~5MB~200k blobs ~200MB~2M+ blobs ~2-5GB on R2: ~$0.075
GitHub Packages bandwidth~£0 (1-2 consumers)£5-20 if multiple federations pull weekly£20-100, depends on cache hit rate
TurnstileFreeFree (well under 1M)Free or Enterprise — verify at scale
Estimated total £/mo£25-40£60-120£4-8k (Supabase-dominated)

Curve bend #1: Supabase 100k MAU

Pro tier includes 100k MAU. Cross that and you pay $0.00325/MAU on top. At 500k that's ~$1,300/mo extra — small. The real bend is when DB compute or egress forces you off Pro entirely. Team is $599 and includes SOC2 reports federations may demand. Enterprise is a sales call with no anchor number.

Curve bend #2: Trait PNG bandwidth

99 PNGs × 100-500KB × every page render is the largest data flow. Served from CF Pages or R2 it is effectively free. Served from a Worker (e.g. to gate access or rewrite URLs) every byte counts against Workers paid tier. The mooted traits.sporthead.id CDN only saves money if it stays a static origin with cache headers — adding a Worker shim inverts the economics.

Curve bend #3: D1 row reads

D1 paid is $0.001/1k reads. Cheap until somebody writes a worker that does row-level lookup on every request without caching. The federation-router stub is exactly that pattern — every cold cache hit is a D1 read. Plan the KV cache layer before the second federation goes live.

03

The "built not bought" OIDC math

ADR-0006 chose to build OIDC on Workers to avoid per-MAU vendor cost. The red-team disputed the build estimate. Here is the run-rate math on both sides.

Option5k MAU50k MAU500k MAUNotes
Build on Workers (current plan)~£20 infra + 6mo eng amortised~£60 infra~£500 infra + ongoing maintenanceInfra cheap; real cost is engineering + ongoing security tax
WorkOS AuthKit1M MAU free, then $2,500 base — so £0 at 5kStill free tier or low Connect bundles ($125/mo for SSO)Enterprise — model £2-5k/moBest-in-class B2B, slightly awkward for B2C identity
ClerkFree under 10k MAU$25 + 40k × $0.02 = $825/mo (~£660)~$8,000/mo (~£6,400)Per-MAU brutal at scale; great DX at small scale
Auth0 B2C$228/mo first 1k MAU then tiers~$1,200/moEnterprise; historically £8-15k/mo at 500kCautionary tale that anchors this debate
Hanko (self-host OSS)~£20 infra~£60-100 infra~£300-500 infraYou own ops; passkey-first; less mature than paid options
Ory Hydra (self-host OSS)~£30 infra~£100 infra~£500-1,000 infraBattle-tested OIDC; you still own JWKS rotation, refresh tokens, etc.

The honest read: the build-vs-buy math is not as flattering as ADR-0006 implies. At 50k MAU, WorkOS is plausibly cheaper than the fully-loaded cost of building (one senior engineer-month is ~£10-15k; 6 months is £60-90k; that's 8-12 years of WorkOS bills at the 50k tier). The build only "wins" if (a) engineering really is 1-2 weeks, which the red-team disputes, and (b) ongoing security tax is zero, which it never is. The right comparison: not "infra bill A vs infra bill B + vendor fee" but "infra bill A + 6 months critical-path delay + ongoing on-call vs vendor fee".

The strongest argument for build is product control over the PIN-as-primary-factor flow and identity-as-domain-noun branding — neither WorkOS nor Clerk make that easy without heavy theming. That is a real reason. "Cheaper" is not.

04

Hidden costs — what isn't in the bill

Engineering time on undifferentiated heavy lifting

JWKS key rotation, refresh-token rotation + replay detection, PKCE downgrade defence, token revocation lists, session pinning. None of this ships product features. At ~£500/day fully-loaded, every two-day rabbit hole on a known-solved problem is £1k that did not buy a Sport Head.

Annual pentest £10-25k/yr

OIDC + VC issuance is a meaningful attack surface. Reputable London/UK testing house: £10-25k for a focused 5-day engagement on auth + credential surface. Budget annually from the moment OIDC is live.

On-call

Red-team flagged single-person on-call risk. PagerDuty for a small team is ~£15/user/mo; real cost is the human one. Two-person rotation minimum; expect a £5-15k/yr hit in retention and weekend pay/comp time once incidents start.

SOC2 / ISO27001 £20-50k/yr

The moment a federation procurement asks "are you SOC2?", you have ~6 months to be. SOC2 Type 2 via Vanta/Drata: £8-15k/yr platform + £15-30k audit. ISO27001 similar. Plan £20-50k/yr blended once any federation customer is paying.

DPIA + ICO consultation

Identity, children-adjacent (sport youth federations), biometrics-ish (helmet rarity tied to identity) is exactly ICO-published-guidance territory. Solicitor-led DPIA: £5-15k once; lower ongoing.

Two-founder bus factor

Jonny and Liam are the only operators of every system documented here. Replacing either is a senior hire at £80-120k fully-loaded plus 3-6 months ramp. A known liability on the cost ledger.

05

Vendor lock-in matrix

Score each vendor: difficulty of leaving, data extractability, code portability. 1 = trivial to swap, 5 = effectively permanent.

VendorDifficulty to leaveData extractabilityCode portabilityNotes
Cloudflare Pages1n/a (static)1Any static host; trivial.
Cloudflare Workers (Hono)2n/a2Hono runs on Node, Bun, Deno, Lambda. Watch for CF-specific APIs leaking into business logic.
Cloudflare D1222SQLite-compatible — dump and restore anywhere.
Cloudflare KV333No SQL semantics; enumerate keys via API to export. Re-platforming means picking Redis/Upstash/DynamoDB and rewriting access patterns.
Cloudflare Turnstile1n/a1reCAPTCHA / hCaptcha drop-in.
Supabase Auth533The big one. Passwords are bcrypt-hashed (extractable), but PIN hashes, JWT format, refresh-token rotation behaviour, and GoTrue endpoint contract are proprietary. Migrating auth means dual-running both systems until every user re-authenticates. Expect a 12-month tail.
Supabase Postgres254It is Postgres. pg_dump moves you to RDS/Neon/self-hosted in an afternoon. RLS policies are SQL.
Supabase Storage243S3-compatible API; move the bucket, repoint clients. Storage RLS layer needs re-implementing.
GitHub Actions3n/a3YAML port to GitLab CI / Buildkite / Jenkins is annoying but mechanical.
GitHub Packages323URLs are GitHub-specific. SHOTclubhouse points at npm.pkg.github.com; moving to private NPM means coordinated flips.
did:web:sporthead.id5n/an/aPermanent. Every VC issued points to this domain. Changing the issuer DID invalidates every credential in the wild. Lock-in to a domain name. Treat sporthead.id renewal as critical infrastructure with explicit auto-renewal monitoring.
06

The 100k MAU "wall" scenarios

Inflection points where the architecture or the bill needs rethinking.

CohortRealistic £/moWhat changes architecturally
10k MAU£60-150Supabase Pro confirmed. CF Workers paid. Light caching matters but nothing on fire.
100k MAU£1-3kSupabase Team ($599) is the floor for SOC2 reports federations will demand. Read replicas discussed. GitHub Packages bandwidth metered. Annual pentest line item appears.
1M MAU£10-30kSupabase Enterprise (custom; expect £5-10k+). CF Workers paid usage meaningful. Dedicated SRE hire becomes plausible. Compliance overhead £30-60k/yr blended.

Unit economics: at 100k MAU with ~£1.5k/mo bill, that's ~£0.18/Sport Head/year. At 1M MAU with £20k/mo, £0.24/SH/yr. Infrastructure scales sub-linearly — good news. Operational and compliance cost scales super-linearly — every 10× increase brings a new compliance regime, pentest scope, threat model. Budget on operational headcount, not vendor invoices, above 100k MAU.

For the business to support this load, revenue per Sport Head needs to be ~£1-2/yr minimum — not from the Sport Head (free) but from the federation paying for the portal. The unit math sits squarely on the federation deal.

07

"What if we ditched X" — option pricing

don't

Drop Cloudflare for AWS

Lambda + S3 + CloudFront + DynamoDB. Similar bill at small scale, materially more expensive at edge-heavy scale (Lambda@Edge pricier than Workers). Operational complexity goes up. Lock-in shifts to AWS, which is at least equally sticky. No reason unless a federation explicitly demands AWS.

maybe at scale

Drop Supabase for Neon + Lucia / Better Auth

Neon cheaper than Supabase Team at comparable scale (~£100-300 at 100k MAU). Lucia/Better Auth give Postgres-native auth without vendor lock. Trade: no Storage (need R2), no Realtime, no GoTrue — you write glue. Realistic gain: ~£300-500/mo at 100k MAU, paid for with 1-2 engineer-months. Worth considering at 100k inflection, not before.

worth reopening

Replace OIDC plan with WorkOS

£0-200/mo at 5k MAU, scaling. Removes 6 months of engineering from critical path. Pros: ship federation portal faster, get SOC2-able auth for free, stop carrying on-call risk on homemade OIDC. Cons: lose product control over PIN-first flow; brand surface is theirs not yours. Revisit the ADR-0006 decision with this on the table.

do it before launch

Move VC signing to AWS KMS + R2 issuer log

KMS is ~£0.80/key/mo + £0.03/10k operations. R2 ~£0.01/GB-mo, no egress fees. Real key custody (HSM-backed), proper audit log. Adds AWS as a vendor — small, focused, low lock-in surface. Cost at 500k MAU: ~£20-50/mo. Most defensible single change here.

08

The honest unit economics

Federation pays SHOT for a portal. Members are free. Does the federation cheque cover infrastructure + engineering + compliance?

ScenarioRevenueDirect cost (infra + share of ops)Margin band
2 federations × £20k = £40k ARR (year 1)£40k~£5k infra + ~£100-150k eng + ~£10-20k compliance = £115-175kheavy loss — funded by runway
10 federations × £20k = £200k ARR£200k~£20-40k infra + £150-200k eng + £30-50k compliance = £200-290kbreak-even to thin loss
25 federations × £25k = £625k ARR£625k~£100-150k infra/compliance + £250-300k eng = £350-450k~30-40% margin, healthy

Margin gets healthy only at ~20+ federations. Below that, the business is funded by runway, not federation revenue — fine for a launch year but should be on Jonny and Liam's whiteboard as the explicit thing the next 24 months has to deliver. Biggest swing factor is engineering cost, not infrastructure — which is exactly why the "build vs buy" decisions matter more than the £/mo numbers on any vendor invoice.

09

Verdict

Cost verdict

Healthy at the bottom, fragile at the operating-cost middle

The vendor bill itself is not the problem at any plausible 24-month scale — £5k/mo even at 500k MAU is rounding error against a £600k ARR target. The three expensive surprises are: (1) the "we built OIDC to save money" estimate is the wrong frame — 6 months of senior engineering is worth ~10 years of WorkOS bills, and on-call cost is permanent; (2) SOC2/ISO/pentest/DPIA together will be £30-60k/yr the moment federation procurement is serious, and that line item is currently invisible; (3) the did:web domain is the only permanent lock-in in the stack and is currently treated as a regular domain rather than critical infrastructure. The right move: reopen ADR-0006 with WorkOS / Hanko on the table, move VC signing to KMS before launch, get sporthead.id on locked auto-renewal with monitoring this week, and put the compliance line in the runway model now rather than discovering it during the first federation procurement.