When multiple workers share mutable state, you need coordination. Coordination means locks. Locks serialize execution. Under load, locks become the bottleneck—not computation.
Data is a stream passing through generic processors. Any worker can handle any piece of data.
Tick arrives → any available worker grabs it → reads/writes shared state → done
Consequence: Multiple workers touching the same data requires a mutex. The lock becomes a chokepoint.
Data belongs to a specific processor. No one else touches it.
Tick arrives → deterministic routing → only one worker ever sees it → no coordination
Consequence: If only one goroutine can read/write a piece of state, there's nothing to coordinate. No lock, no contention, no cache invalidation.
| Concern | Flow (Shared State) | Ownership (Sharded) |
|---|---|---|
| Lock contention | Grows with workers | Zero |
| Cache coherence | Constant invalidation | Per-core locality |
| Scaling | More workers = more waiting | More shards = more throughput |
| Failure isolation | Shared fate | Independent domains |
The key mechanism: hash the data key to a shard ID.
shardID := fnv32(tick.Symbol) % numShards
workerChannels[shardID] <- tick
BTC always hashes to Shard 0