# Let `Task.async_stream/3` emit fast work first

`Task.async_stream/3` quietly holds fast results behind the earliest slow input because `ordered` defaults to `true`. When independent IO work does not need input order, opt out explicitly and set a bounded concurrency limit.

```elixir
defmodule BillingSync do
  def sync_all(accounts) do
    accounts
    |> Task.async_stream(
      fn account ->
        Billing.fetch_usage!(account)
      end,
      max_concurrency: 20,
      ordered: false,
      on_timeout: :kill_task,
      timeout: 15_000
    )
    |> Enum.each(fn
      {:ok, usage} ->
        Billing.store_usage!(usage)

      {:exit, :timeout} ->
        raise "usage sync task timed out"
    end)
  end
end
```

With ordered output, Elixir buffers later completions until it can emit every earlier input. In a local run with one task sleeping for 200 ms and two sleeping for 10 ms, ordered delivery emitted all three at 204 ms. With `ordered: false`, the two fast results arrived at 11 ms and the slow one at 201 ms. The trade-off is real: results now arrive in completion order, not input order.

`max_concurrency` defaults to `System.schedulers_online/0`, a CPU-oriented default that is often too small for IO-bound work. Choose a higher bounded number only after considering the remote service's rate limit, the HTTP client's pool, and your own capacity.

The per-task `timeout` default is 5,000 ms. Its `on_timeout` default, `:exit`, exits the caller; `:kill_task` instead kills that task and emits `{:exit, :timeout}`. `zip_input_on_exit` also defaults to `false`; enable it when exit results need the original input attached. This changes stream options only—use the `Task.Supervisor` stream APIs when you also need supervision semantics.

[`Task.async_stream/3` docs](https://hexdocs.pm/elixir/Task.html#async_stream/3)


---

Created by: almirsarajcic
Date: July 28, 2026
URL: https://elixirdrops.net/d/KiWh4GLy
