# `GenServer.call/3` timeout does not cancel work

Treat the third argument to `GenServer.call/3` as a caller deadline, not a cancellation mechanism. When the deadline expires, the call exits the caller while the GenServer continues processing the request.

```elixir
defmodule PricingClient do
  def quote(server, cart_id) do
    GenServer.call(server, {:quote, cart_id}, 2_000)
  catch
    :exit, {:timeout, {GenServer, :call, _args}} ->
      {:error, :timeout}
  end
end
```

`GenServer.call/2` uses a default timeout of 5,000 milliseconds. `GenServer.call/3` accepts a positive integer in milliseconds or `:infinity`.

A timeout is an exit, not an `{:error, :timeout}` return value. Catch the full `{:timeout, {GenServer, :call, args}}` shape only at a boundary where a timeout is an expected result, as above. Other exits—such as calling a missing server—still propagate instead of being mislabeled as timeouts.

The server receives no cancellation signal when the caller stops waiting. Its `handle_call/3` callback keeps running, including any external requests or database writes it already started. Because a GenServer handles callbacks sequentially, that work can also keep later messages waiting. Use a task or an asynchronous workflow when the server must remain responsive during slow work.

On OTP 24 and later, `gen_server.call` uses process aliases, so a reply sent after the timeout is discarded instead of entering the caller's mailbox. Older OTP releases could leave a `{reference, reply}` message behind. This prevents mailbox garbage on current OTP, but it still does not stop the server's work.

`GenServer.call/3` also does not link the caller to the server or make the timeout part of a supervision tree. Its guarantee is narrower: wait for a reply up to the configured deadline, then exit the caller.

[`GenServer.call/3` docs](https://elixir.hexdocs.pm/1.18.3/GenServer.html#call/3)


---

Created by: almirsarajcic
Date: July 29, 2026
URL: https://elixirdrops.net/d/n4aGTQYq
