# Give background processes useful labels

PIDs are not much help when several copies of the same worker are running. `Process.set_label/1` adds a term that identifies what each process is doing.

```elixir
defmodule MyApp.Importer do
  use GenServer

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts)
  end

  @impl GenServer
  def init(opts) do
    path = Keyword.fetch!(opts, :path)
    Process.set_label({:importer, path})

    {:ok, %{path: path}}
  end
end
```

Labels can be any term and do not have to be unique. You can use the same label for a group of workers or include a value, such as the path of the file being imported, to tell them apart.

Observer includes the label in its process list, and crash reports include it too. Seeing `{:importer, "orders_2026_08.csv"}` in a report is usually more useful than seeing a PID alone.

This is separate from process registration. A registered name is used to look up a process and must be unique within its registry. A label is only metadata, so it is safe to use values that are created at runtime.

```elixir
# Include enough context to identify the work.
Process.set_label(:cache_warmer)
Process.set_label({:session, user.id})
Process.set_label({:webhook_retry, event_id, attempt})
```

GenServers are not special here. A supervised task can set its own label in the same way:

```elixir
Task.Supervisor.start_child(MyApp.TaskSupervisor, fn ->
  Process.set_label({:thumbnail, upload.id})

  generate_thumbnail(upload)
end)
```

`Process.set_label/1` is available in Elixir 1.17 and later. `Process.get_label/1`, which reads another process's label, was added in Elixir 1.20. With earlier Elixir versions on OTP 27 or later, use `:proc_lib.get_label/1`.

[Process.set_label/1 docs](https://hexdocs.pm/elixir/Process.html#set_label/1)


---

Created by: almirsarajcic
Date: August 17, 2026
URL: https://elixirdrops.net/d/v2u74x6a
