> aren't reliable if an async/coroutines moves threads between calls

Then just don't move them between threads and you're good with thread locals, no?

Iirc often the frameworks don't have worker affinity, anyhow environments like .NET has "AsyncLocal" to provide an aware alternative.