Skip to content
Task and Task.async/await
step 1/5

Reading — step 1 of 5

Learn

~1 min readTasks, ETS, Macros

For one-off async work, Task is simpler than full GenServer. Like Promise/Future but using Elixir's process model.

task = Task.async(fn ->
    Process.sleep(100)
    :computation_result
end)

# Other work happens here, in parallel

result = Task.await(task, 5_000)   # block up to 5s

Parallel execution:

tasks = Enum.map(urls, fn url ->
    Task.async(fn -> fetch(url) end)
end)

results = Enum.map(tasks, &Task.await(&1, 30_000))

Task.async_stream — better for many tasks; controls concurrency:

urls
|> Task.async_stream(&fetch/1, max_concurrency: 4, timeout: 30_000)
|> Enum.to_list()
# [{:ok, result1}, {:ok, result2}, ...]

max_concurrency caps how many Tasks run at once. Useful for rate limiting.

Task.Supervisor — supervised tasks (recommended for production):

# In your supervision tree:
children = [
    {Task.Supervisor, name: MyApp.TaskSup}
]

# Then:
Task.Supervisor.async_nolink(MyApp.TaskSup, fn -> ... end)

async_nolink is like async but the calling process won't crash if the task does — error becomes a message you can match on.

Task.start — fire-and-forget, no result expected:

Task.start(fn -> log_event(event) end)

Differences from GenServer:

  • Task: one-shot computation
  • GenServer: long-lived stateful server

Most concurrent code in Elixir uses Task for parallel work + GenServer for state.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…

Task and Task.async/await — Elixir Advanced