Using Process.send_after() outside of a GenServer?

I would answer your second question ‘no’. Tracking state is a sound reason to reach for GenServer. The main anti-pattern around GenServer is to use them for code organization. Conversely, docs say:

Use processes only to model runtime properties, such as mutable state, concurrency and failures, never for code organization.

which clearly applies to your case: GenServer — Elixir v1.12.3

That said, have you seen HTTPoison.Retry — httpoison_retry v1.1.0 I think there may also be http libraries with retry support built in…