NXT

Cost and scaling

Per-user cost today and where bills hit at 1K / 10K / 100K monthly active users

Numbers reflect public pricing as of 2026-05-26. Re-verify before quoting.

Per-user cost today

Assume a moderately engaged user: opens the app 3× per week, browses 10 schools per session, opens 5 college detail pages per session, saves 2.

Cost driverPer sessionPer month
Convex bandwidth + function calls$0 (free tier)$0
OpenAI blurb (5 detail opens × first-open cost ~$0.0003)~$0.0015~$0.018
Subsequent blurb opens (cache hit)$0$0
Scorecard API (cache hit on warmed schools)$0$0
logo.dev$0 (free tier)$0
Serper hero images (cache hit on warmed schools)$0$0
Push notifications (FCM / APNS)$0$0
PostHog ingest$0 (free tier)$0
WorkOS active userincluded in tier

Estimated marginal cost per moderately engaged MAU: ~$0.02/month.

This is the AI blurb + cache hit on data. New cold-fetched colleges (first time anyone in the system encounters them) carry a small one-time cost for logo + hero image; amortized across the user base it's negligible.

Where the bills hit

Convex

  • Free tier: up to 1M function calls, 1GB DB storage, 1GB bandwidth/month.
  • Pro tier ($25/month/team member): 25M function calls, 8GB storage, 50GB bandwidth.
  • Linear pricing above pro: see convex.dev/pricing.

At ~1K MAU the free tier covers everything. At ~10K MAU you're solidly in Pro tier. At ~100K MAU you're paying for incremental function calls + storage; budget ~$300–600/month depending on access patterns.

The dominant cost grower is useQuery subscriptions — every active session holds a live subscription. Closing unused subscriptions (useQuery outside view boundaries) is the lever.

OpenAI

  • gpt-5.4-nano input: ~$0.20/M tokens. Output: ~$0.80/M tokens (verify at openai.com/api/pricing).
  • Each blurb: ~500 input tokens (structured user + college facts) + ~150 output tokens = ~$0.00022 per blurb.
  • 30-day cache means each (user, school) pair generates at most one blurb per month.

At 10K MAU, ~5 detail opens/session × 12 sessions/month = 60 unique-or-cached opens × cache hit rate ~80% = ~12 new blurbs/month/user. ~12K × $0.00022 = ~$2.64/month for 1K MAU. ~$26/month for 10K MAU. ~$264/month for 100K MAU.

Scorecard API

Public, free, no quota declared. NXT hits Scorecard:

  • Once per school per cold fetch (cached in colleges table).
  • Once per school per monthly refresh (no-op for unchanged docs).

At 6,000 active institutions, monthly refresh = 6K calls. Fully sustainable on the free tier indefinitely.

Serper

$0.30 per 1,000 queries. Each new (cold) school = ~1 query for hero image. At 6K total institutions × $0.30/1K = **$1.80 one-time** to warm the entire hero image cache. After that, only newly-released institutions or cache evictions cost anything. Effectively $0/month at steady state.

logo.dev

Free tier: 1,000 logo fetches/month. Same caching as Serper. At steady state, effectively $0/month after initial warm.

WorkOS

  • Free tier: 1M monthly active users.
  • Currently free.
  • AuthKit Pro features (SSO, SCIM, fine-grained roles) move to paid tier; not used today.

Vercel

  • Free Hobby tier covers personal sites only.
  • Pro at $20/month/seat is what production marketing site needs.
  • Bandwidth is the cost driver. At ~10K MAU, the marketing site is probably under the Pro tier's 1TB bandwidth allowance.

EAS Build

  • 30 free builds/month for Production tier ($99/month) or pay-per-build $1–4 depending on machine size.
  • A typical release week: 4–8 builds (preview, staging, production iOS + Android). Easily within the Production tier.

Apple Developer Program

$99/year, fixed.

Google Play Console

$25 one-time fee, already paid.

Total infrastructure cost estimates

MAUConvexOpenAIWorkOSVercelEASApple/PlayTotal/month
1K$0 (free)~$2.64$0$20$99~$8~$130
10K~$50~$26$0$20$99~$8~$200
100K~$400~$264~$1K$40$99~$8~$1,800

Estimates are conservative. Verify each line at the actual provider before quoting to a board.

What breaks at 10K MAU

Probably nothing. The architecture was designed for ~10K MAU as the day-one expected ceiling.

The first thing that would measurably feel slower is the discover.rails single-roundtrip query (see Status). p99 latency on that query grows with rail complexity. Splitting into nine per-rail queries is a known optimization.

What breaks at 100K MAU

Several things become worth solving:

  1. Convex subscriptions. Active subscription count grows with concurrent sessions. Convex handles this, but cost grows linearly. Lever: aggressive useQuery scoping.
  2. OpenAI per-blurb cost. Could grow to $250+/month. Lever: harder cache (per-cohort blurb instead of per-user), or move to a cheaper provider.
  3. colleges table size. 6K institutions × 30 KB of nested data ≈ 180 MB. Well within Convex limits but worth understanding.
  4. Cron fan-out. The weekly new-matches cron iterates active users in 500-row pages. At 100K active users, the chain depth is 200. The chain is bounded but the per-week compute scales linearly.
  5. scorecard refresh write pressure. Monthly. 6K upserts in a window. Convex handles it; budget a 5-minute window per refresh.

None of these is a cliff. All are linear scaling.

Cost optimizations that have NOT been done

In priority order, where dollars (not engineering hours) become the constraint:

  1. Move push delivery to a transactional provider if FCM/APNS hit rate limits. Resend or AWS SNS would be the fallback.
  2. Cohort-level blurb caching. A "for users with profile X" cached blurb instead of one per user. Cuts OpenAI cost by ~10×. Trade-off: less personalized copy.
  3. Aggregate components (aggregateWorkforce, aggregateTransferOutcome) fully replacing by_active_score. Reduces top-N read cost.
  4. Edge caching the public marketing site. Vercel's free CDN already handles this; only pull this lever if Vercel bandwidth becomes meaningful.

Technical detail

Why OpenAI cost isn't bigger

The 30-day cache + the fact that the blurb is a ~150-output-token generation. The model is cheap; the request is short; the cache absorbs the rest.

Where Convex cost comes from

Convex bills on (a) function call count, (b) database storage, (c) bandwidth in/out of the deployment. Subscriptions don't bill separately, but every subscription update is a function call internally.

Why staging Convex would double infra cost

A second deployment doubles the storage line (same data, two copies if synced; sparse data otherwise) and doubles the cron-firing cost. Decision in Deployment was to skip staging Convex on this trade-off.

On this page