casty · performance sweep · replicated virtual actors

How the cluster scales: sharding rules, cluster size charges a toll

39 load points sweeping cluster size, concurrency and actor count, at peak capacity (no rate cap), 30 s each. Against replicas=3, write=MAJORITY. Throughput is bounded by quorum replication latency, not by CPU: more actors buy parallelism, more nodes charge latency, and a single hot key is a hard ceiling at ~5k ops/s.

25.5k
peak throughput (ops/s)
15 nodes · 250 writers · ≥100 actors
~5.1k
hot-key ceiling
1 actor, invariant to nodes and writers
−48%
15 → 100 nodes
throughput falls with the cluster, it does not rise
0
errors in 18.7M writes
consistency intact across the whole grid
01

Throughput × actor count

Each line is a cluster size. On the left, 50 writers; on the right, 250. 1 actor is the hot-key floor — a single owner serializes everything. Throughput jumps as soon as the keyspace spreads out, saturates at a plateau, and decays ~5–7% at 20 000 actors (activation/memory cost). Concurrency from 50→250 writers lifts the plateau ~40% on the small cluster; on the larger ones the gain vanishes — it becomes latency-bound.

50 writers

ops/s vs actors (x log)

250 writers

ops/s vs actors (x log)

15 nodes 50 nodes 100 nodes (partial)
02

p99 latency × actors — the under-sharding cliff

With 50 writers (left) the tail is placid: p99 stays at 6–9 ms across the whole range. With 250 writers (right) and few actors, concurrency piles up in the FIFO mailboxes and the tail explodes: p99 of 120 ms (15 nodes) and 218 ms (50 nodes) at 25 actors. From ~100 actors on, the tail collapses to ~23–30 ms. Rule of thumb: actors ≳ 4× writers to keep the tail flat.

50 writers

p99 ms vs actors (y log)

250 writers

p99 ms vs actors (y log)

15 nodes 50 nodes 100 nodes (partial)
03

The cluster-size toll

Plateau throughput (100 actors) against node count. With replicas=3 fixed, adding nodes does not add replication parallelism for a given keyspace — it only spreads owners and backups across more distant hosts, stretching the quorum round-trip. More nodes = more latency = less throughput per client.

ops/s at the plateau (100 actors)

vs cluster size

04

Patterns

P1

The hot key is a hard ceiling at ~5k ops/s

1 actor delivers ~5.1k ops/s regardless of nodes (5.3k / 5.2k / 5.1k) or of writers (250 writers give the same ~5k, only with p99 going 50→85 ms). The single owner serializes handlers (FIFO mailbox, 1 at a time) and every write pays the MAJORITY round-trip. Neither concurrency nor a larger cluster breaks through this — only sharding.

P2

A larger cluster costs throughput, it does not gain it

Plateau: 15 nodes → 25k, 50 nodes → ~15k, 100 nodes → ~13k (−48% from 15 to 100). The bottleneck is quorum replication latency, not node CPU: spreading owners+backups across more hosts stretches the write=MAJORITY path. A large cluster is about state capacity (more actors fit), not about ops/s per client.

P3

Concurrency is the lever; actors only need to be enough

Well sharded, 50→250 writers raises the plateau ~40% on the small cluster (18k→25k). Throughput is ≈ concurrency ÷ latency: from ~25 actors on in the 50-writer case, the ceiling becomes the number of writers in flight itself. Actors beyond what is needed do not help — they just must not be too few.

P4

Under-sharding is a tail cliff, not a median cliff

250 writers on 25 actors: median still healthy (~5–7 ms) but p99 of 120–218 ms — deep queues in the few mailboxes. The median hides it; the p99 exposes it. Size the keyspace by concurrency, not by average load.

P5

20 000 actors is viable, at a gentle cost

Jumping from 2.5k to 20k actors costs ~5–7% of throughput and a few ms of p99 (on-demand activation + memory for more activations). No cliff, no errors. Virtual actor density holds up in the tens of thousands.

P6

Correctness intact under all load

Zero write errors across 18.7 million acked adds over the entire grid — every ack was reflected in the final value. Pressure showed up as latency, never as loss.

05

Full grid

ops/s (p99 in ms). Cell in red = hot-key floor; cyan = peak.