Skip to main content
Numbers are per-process throughput. SQLite is single-writer, so vertical scaling of writes is bounded. Reads scale across a connection pool.
The values below were measured on earlier reference hardware (a 2024 Apple M-series laptop, 16 GB RAM). They are pending re-measurement on the current reference machine (2025 Mac Studio M3 Ultra, 96 GB). Treat them as a lower bound until refreshed.
Re-run with:

Data plane (single-writer SQLite)

Realtime path

The WS hub broadcast number measures the enqueue side. It fans out to 16 shard worker threads, and each thread pushes to its connected clients. The real delivery rate depends on client count, message size, and TCP send buffers.

Change log memory

The server keeps recent change events in memory, so a client that reconnects can catch up. The ring holds at most 10,000 events and 32 MiB of event data, whichever limit comes first. Events that leave the ring stay in _pylon_change_log on disk (SQLite), where a client that is further behind reads them. Apps that rewrite large rows often, such as a chat transcript updated while a model streams, fill the byte limit first. To change it, set PYLON_CHANGE_LOG_MEMORY_MB. PYLON_CHANGE_LOG_RETAIN sets how many events stay on disk (default 100,000).

What these numbers mean for deploy sizing

Small (1 vCPU, 1 GB RAM, ~$5/mo VPS)

  • Up to ~20k writes/minute sustained, or bursts to 30k/minute
  • Up to ~10k concurrent WS connections (64 KB stack per reader thread)
  • Good for a few thousand active users at typical web app request rates

Medium (2 vCPU, 4 GB RAM, ~$25/mo VPS)

  • Up to ~50k writes/minute sustained
  • Up to ~40k concurrent WS connections
  • Good for 50k active users, with room for complex queries without cache eviction

Large (4+ vCPU, 8+ GB RAM)

  • The write ceiling is still single-writer SQLite (about 70k inserts/sec peak). If writes are your bottleneck, move to Postgres (postgres-live feature) or shard the app across databases.
  • Reads scale with the read-connection pool. 4 pool connections × 500k reads/sec = 2M reads/sec ceiling.

When to switch backends

Switch from SQLite to Postgres when

  • Sustained write rate > 50k/sec (you are at SQLite’s single-writer limit)
  • Multiple processes need to write (replicas, HA failover)
  • You need online DDL / zero-downtime migrations at scale
  • Storage > 100 GB (not a hard limit, but WAL checkpoints get painful)

You can stay on SQLite when

  • Single-process deployment
  • Full DB fits comfortably in RAM for the read pool
  • You back up with pylon backup on a schedule

On Stack0 Cloud

Cloud supports multiple application machines for Postgres projects. It uses the managed PylonSync relay for cross-machine realtime events. SQLite projects must stay on one application machine. Resize the machine or switch to Postgres before you add replicas. For multiplayer apps with sticky shard connections, latency to your players matters. Set the workspace region accordingly when you sign up.

Benchmark gaps

  • Multi-client read contention (connection-pool fair-share)
  • TLS handshake cost (reverse proxy terminates TLS)
  • Network round-trip time: production numbers will be bounded by the network first
  • Shard tick budget for realtime game state: depends on SimState::tick
For a real capacity estimate under your workload, run cargo bench -p pylon-runtime (see the commands at the top of this page) against a representative fixture and the manifest you will ship with.