Skip to content

Cost & Scaling

What the platform costs to run, and what has to change as it grows.

These are list-price estimates

Derived from the Terraform configuration and DigitalOcean's published pricing. Validate against the actual invoice — usage-based services (Mux, Spaces bandwidth, CDN) vary with traffic, and make cost in infra/terraform deliberately points you at the DigitalOcean calculator rather than guessing.

Fixed monthly cost

ItemConfiguration≈ / month
Kubernetes nodes3 × s-4vcpu-8gb$144
Kubernetes control planeStandard$0
Managed PostgreSQLdb-s-2vcpu-4gb, 1 node$60
LiveKit droplets-4vcpu-8gb$48
Load Balancer1$12
Container RegistryBasic tier$5
SpacesBase, 250 GB included$5
Block storage25 GB (Loki 20 Gi + Redis 5 Gi)$3
Subtotal≈ $277

Usage-based

ServiceDriverNotes
MuxMinutes encoded, minutes deliveredThe most variable line. Video-heavy growth shows up here first
Spaces bandwidthCDN egress beyond the included allowanceGrows with media consumption
Node autoscalingLoadPool scales 2–10; each extra node is $48
RevenueCatTransaction volumeFree below a revenue threshold, then a percentage
StripePayout volumePer-transfer fees
BugsnagEvents
Expo / EASBuild minutes

Realistically $300–450/month all-in at modest usage, with Mux the line most likely to surprise.

Cost levers

LeverSavingTrade-off
Drop to 2 nodes−$48Less headroom; autoscaling still covers bursts
Smaller LiveKit droplet−$24Fewer concurrent voice participants
Self-hosted Postgres in-cluster−$60You own backups, failover, and upgrades. Not recommended
Spaces lifecycle rules on originalsStorageOriginals are currently kept forever after processing
Loki retention policyStorageCurrently unbounded until the 20 Gi fills

A single-droplet alternative exists on paper

dev-notes/single-droplet-feasibility-analysis.md concludes the whole stack fits on one 4 GB / 2 vCPU droplet (~$24/month plus external services) for 200–500 concurrent users.

That is a genuine option for a much earlier stage, but it trades away everything Kubernetes is providing here: zero-downtime rollouts, replica-level redundancy, autoscaling, and managed database backups. Given the platform is live and handling real money, the current setup is the right call. Note also that the analysis's comparison figure ($148–153/month) reflects a smaller cluster than the one currently configured.

What breaks first as you grow

In the order it will actually happen:

1. Database connections

db-s-2vcpu-4gb has a bounded connection limit. Three API replicas plus esu, ogun, anansi, and igdb-heartbeat each hold a Prisma pool. Adding API replicas multiplies connections, so the database limit caps horizontal scaling of the API before CPU does.

Fix: a connection pooler (PgBouncer, or DigitalOcean's managed pooler). Cheap, and it should be done before scaling the API.

2. Redis as a single point of failure

One replica backing the queue, realtime fan-out, caching, and the payout lock. A restart interrupts all four.

Fix: DigitalOcean Managed Redis with HA. Roughly $15–60/month depending on size.

3. redis.keys() on every post

Feed cache invalidation calls KEYS, which is O(N) over the entire keyspace and blocks the Redis server while it runs. At current volume it is invisible; as the keyspace grows it becomes a latency spike felt by every service sharing that Redis.

Fix: SCAN, or track each user's cache keys in a Redis set. Contained change, no infrastructure cost.

4. The discover feed

prisma.user.findMany() with no limit — it returns every user on the platform. It will get slower in proportion to signups and eventually time out.

Fix: proper ranking, filtering, and pagination. See Discovery.

5. Presence across esu replicas

Presence is an in-memory map per pod, so online status is already inconsistent across the two replicas. It gets worse with every replica added.

Fix: move presence into Redis.

6. Media processing throughput

ogun autoscales 2–8 on CPU, which handles bursts. The next ceiling is Mux's rate limits on asset creation.

7. Mux costs

Encoding and delivery both scale with video volume. Watch this line specifically as clip usage grows; video_quality: "basic" is already the economical setting.

Scaling actions in order

SignalActionCost
API CPU sustained highAdd API replicas — but check database connections first$0 until a node is added
Postgres connection errorsAdd a connection pooler~$15
Nodes at capacityThe pool autoscales to 10$48 per node
Redis latency or restartsMove to Managed Redis with HA$15–60
Database CPU or storage pressureResize the managed clusterStep up in tiers
Media backlog growingogun HPA handles it; raise maxReplicas if neededNode cost only
Voice quality degradingLarger LiveKit droplet, or a second one$24–48

Things worth spending money on

Not all of these are infrastructure, and the non-infrastructure ones are the better investment:

InvestmentCostReturns
Staging environment$30–50/monthStops untested changes reaching production. Highest value per dollar here
Managed Redis$15–60/monthRemoves a single point of failure
Connection pooler~$15/monthUnblocks API scaling
CI/CD$0 (GitHub Actions free tier)Automated verification and traceable deploys
Alerting$0 (Grafana already deployed)Find outages before users report them
Uptime monitoring$0–10/monthCatches the case where the cluster is down and therefore not logging

Three of the six cost nothing and are limited only by engineering time.

Efficiency already in place

Worth noting, because it is the reason costs are as low as they are:

  • Aggressive image caching (max-age=31536000, immutable) — the CDN serves almost everything
  • Redis caching on the feed (60 s) and trending (5 min) — the expensive queries run rarely
  • Presigned direct-to-Spaces uploads — media bytes never consume API bandwidth or CPU
  • video_quality: "basic" on Mux — the cheaper encoding tier
  • withoutEnlargement on image resizing — no wasted work upscaling small originals
  • Node autoscaling from 2 — the cluster scales down when idle

Internal documentation — PlayPalz platform