The Core Problem

When multiple workers share mutable state, you need coordination. Coordination means locks. Locks serialize execution. Under load, locks become the bottleneck—not computation.


Two Mental Models

Flow Mindset

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.

Ownership Mindset

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.


Why Ownership Wins

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

Implementation Pattern: Deterministic Routing

The key mechanism: hash the data key to a shard ID.

shardID := fnv32(tick.Symbol) % numShards
workerChannels[shardID] <- tick