# How are you meant to use Select.async correctly?

**URL:** <https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129>\
**Category:** Help\
**Tags:** standard-library\
**Created:** [October 28, 2026, 6:04pm UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129 "2026-10-28T18:04:14Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![InspectorBoat](https://ziggit.dev/user_avatar/ziggit.dev/inspectorboat/32/10410_2.png) [@InspectorBoat](https://ziggit.dev/u/InspectorBoat)\
**Post date:** [October 28, 2026, 6:04pm UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129/1 "2026-10-28T18:04:14Z")

</div>

1. The implementation is allowed to run the task eagerly, blocking the calling thread before the `Select.async()` call even returns
2. The task has to append its completion value to a blocking queue before it can finishes
3. The queue has a limited capacity

So, if the queue is full, and nobody is consuming results with `select.await()` (this will easily happen if the task that spawns `Select.async` tasks is the same task that calls `Select.await`), any call to `select.async()` can deadlock.

This sounds a rather serious footgun. So by my understanding, to use `Select.async`, you have to guarantee one of the following:

- There is enough capacity in the internal queue for the result, _including any other in-flight tasks._ This is kind of annoying because you have to track the number of in-flight tasks yourself.
- Someone else is calling await concurrently.

---

<div class="post-metadata">

**Author:** ![InspectorBoat](https://ziggit.dev/user_avatar/ziggit.dev/inspectorboat/32/10410_2.png) [@InspectorBoat](https://ziggit.dev/u/InspectorBoat)\
**Post date:** [October 28, 2026, 6:06pm UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129/2 "2026-10-28T18:06:07Z")

</div>

I’m not sure if this is an intended (or at least unavoidable) effect of how Select works, but it should probably at least be documented?

---

<div class="post-metadata">

**Author:** ![Southporter](https://ziggit.dev/user_avatar/ziggit.dev/southporter/32/2500_2.png) [@Southporter](https://ziggit.dev/u/Southporter)\
**Post date:** [October 28, 2026, 7:23pm UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129/3 "2026-10-28T19:23:43Z")

</div>

> [@InspectorBoat](#):
>
> 1. The implementation is allowed to run the task eagerly, blocking the calling thread before the `Select.async()` call even returns

I don’t think this is unique to Select. This behavior is true for any of the `async` functions for Group, Batch, etc. This comes from [Asynchrony is not Concurrency](https://kristoff.it/blog/asynchrony-is-not-concurrency/) in that calling async says that it doesn’t matter the order in which it is run. It could be run immediately if the underlying implementation determines that should be done. Calling `.concurrent()` should be used in any cases where it MUST not block.

* * *

For the rest of you post, I think you have the right read on it, however I would push back on whether Select is the right thing to use in the case where you are spawning more tasks than the queue can handle. `Select` is supposed to be used for cases where you want at least N tasks to complete and cancel the rest at that point. The key use case is DNS requests where you don’t care which one succeeds, so long as one of them completes and you take the first result.  
I’m not sure of a case that would lead to what you are outlining for the design of `Select`.

---

<div class="post-metadata">

**Author:** ![InspectorBoat](https://ziggit.dev/user_avatar/ziggit.dev/inspectorboat/32/10410_2.png) [@InspectorBoat](https://ziggit.dev/u/InspectorBoat)\
**Post date:** [October 28, 2026, 7:54pm UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129/4 "2026-10-28T19:54:54Z")

</div>

> [@Southporter](#):
>
> I don’t think this is unique to Select.  
> […]  
> Calling `.concurrent()` should be used in any cases where it MUST not block.

Of course. The issue is that the implementation can make _any_ task a “must not block” task, and this is not immediately obvious.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [October 29, 2026, 1:03am UTC](https://ziggit.dev/t/how-are-you-meant-to-use-select-async-correctly/18129/5 "2026-10-29T01:03:35Z")

</div>

I think that this reply misunderstands what @Southporter is saying. I take what they wrote to mean “What you should do is write `.concurrent()` in your code if the deadlock in your code is a real possibility that must be avoided.” What I take you to mean is that the implementation is free to _run a task synchronously,_ which is a bit different in my reading than saying that the implementation _makes it into_ a “must not block” task.
