Many engineers assume that spawning async tasks in order means they will complete in roughly the same sequence. In Tokio, scheduling guarantees cooperative progress, but it provides zero guarantees regarding execution ordering. When services fan out thousands of subtasks per event without backpressure, memory usage explodes unexpectedly.
Consider an event-driven pipeline processing messages with up to one thousand tokens each. Spawning one Tokio task per token inside an unbounded JoinSet appears harmless when individual outbound I/O calls resolve within milliseconds. However, if early tasks yield on socket reads, the runtime continues scheduling newly spawned tasks. Hundreds of thousands of partially completed task states accumulate on the heap simultaneously, preventing parent events from completing and retaining gigabytes of memory buffers.
Throughput plummets not because of slow networks, but because excessive concurrency exhausts memory allocators through internal fragmentation. Limiting active tasks with semaphores or chunking JoinSet batches restores predictable memory profiles. Concurrency without backpressure is merely an unmanaged queue hidden in your runtime heap.
