Usage-shaped bills

Scale path

10 million accounts is a capacity story, not a rewrite. Pay for the two hot processes when they exist.

StageWhat you runWhat you pay
Pitchnext dev$0
Private betaNext + DATABASE_URL (Neon/Supabase)Database usage + PITR
CA launchAbove + Stripe + REDIS_URL + one Fly/Railway realtimeUsage on Redis, Connect fees, one small VM
Multi-cityRegion env GIGRENTALS_REGION, same imageMore DB/Redis, still one monolith
10M accountsExtract realtime + dispatch worker; Kafka only if the bus is hotThose two services' compute

GPS at 3–5s never writes Postgres on the hot path. That is how 100k concurrent drivers stay off the database invoice. Matching is a 2s tick, not a per-ping optimization.

Loop · Every 3–5s per online driver

GPS ingest

Hot path writes presence only. Postgres is sampled every 30 seconds so 100k drivers do not melt the database.

POST /api/v1/geo/pings
  1. Driver app or socket sends lat/lng.
  2. Cell ids computed with H3 resolution 9 (block) and 8 (neighborhood).
  3. Previous cell membership is removed; new cell set is updated.
  4. A 30s sample flag decides whether to park a durable row in the outbox.

backend/modules/geo/application/ingest.ts

LocationIngest.pingRedis/memory upsert + downsample key

backend/modules/geo/infrastructure/presence-store.ts

PresenceStore.upsertH3 r8/r9 membership sets, 45s TTL

backend/realtime/socket-server.ts

driver:pingSame ingest over WebSocket

$0 demo: Memory hash + sets inside the Next.js process.Scale: REDIS_URL (Upstash). No Kafka required for presence.