Skip to content

Structured Concurrency

A discipline (not a specific library) that guarantees every concurrently spawned task's lifetime is bounded by an enclosing scope — no task can "escape" and keep running unsupervised after its parent scope exits. The structural fix for the orphaned-task class of bugs that plagues unstructured create_task()-style concurrency.

flowchart LR Junior["Junior: the orphaned task problem"] --> Middle["Middle: scoped concurrency - a task cannot outlive its scope"] Middle --> Senior["Senior: error propagation and sibling cancellation"] Senior --> Professional["Professional: structured concurrency in practice - Kotlin coroutineScope, Python trio, Swift TaskGroup"]
flowchart LR subgraph Unstructured["Unstructured (dangerous)"] Spawn1["create_task()"] --> Escapes["Task reference discarded -\nkeeps running, UNSUPERVISED,\nforever"] end subgraph Structured["Structured (safe)"] Scope["async with task_group() as tg:"] --> Spawn2["tg.spawn(...)"] Spawn2 --> Bounded["GUARANTEED to complete\nOR be cancelled BEFORE\nthe 'with' block exits"] end

Choose a level

Level Guide You are done when
Junior The orphaned task problem You can explain why create_task() without tracking the returned task is a real bug risk.
Middle Scoped concurrency You can implement a task-group-style scope that waits for all spawned tasks before exiting.
Senior Error propagation and sibling cancellation You can explain what should happen to sibling tasks when one fails inside a structured scope.
Professional Structured concurrency across languages You can compare Kotlin's coroutineScope, Python's trio nurseries, and Swift's TaskGroup.

Practice rule

Before calling create_task() (or equivalent) and discarding the returned handle, ask: "does anything guarantee this task completes, fails visibly, or gets cancelled before my function returns?" If not, you've created an orphaned task — structured concurrency exists specifically to make this question unnecessary to ask.