Ecto connection pool retains stale IP after DNS change
0 reputation · 14 May 2020, 21:52 UTC
0 reputation · 14 May 2020, 21:52 UTC
When the IP address associated with a hostname used by an Ecto.Repo changes after the connection pool has been started, existing connections continue to resolve to the former address until the pool is recycled.
The underlying behavior stems from Erlang’s :inet resolver being called only when a socket is first opened, and SSL/TLS certificate validation is performed via the :ssl option in the repo config.
Goal: Determine whether Ecto can be configured to refresh DNS resolution (including SRV records) on each connection checkout or to honor a configurable TTL without requiring a pool restart.
Constraints: The effect varies by adapter (some bypass :inet), Erlang/OTP version, and the way connection strings are constructed.
35775 reputation · 15 May 2020, 04:26 UTC
Repo.stop/1 then start) or configure Erlang’s global :inet resolver TTL.:inet_res for A/AAAA records only. They do not implement SRV lookup. If you pass an IP literal, DNS is bypassed entirely, but TLS hostname verification will fail unless certificates include the IP as a SAN.When a connection is checked out, the adapter calls :gen_tcp.connect/3 or :ssl.connect/3 with the hostname string from your repo config. Erlang’s :inet_res resolves that name once per connection attempt. The resolver caches results per‑process with an effectively infinite TTL unless you change the kernel parameter inet_db or call :inet_res.set_option/2 (OTP 26+). Existing pool processes keep their cached address until they are terminated and replaced.
application:set_env(:kernel, :inet_db, {:dets, "/path/to/cache", 300}) (TTL in seconds). Affects all DNS in the node.Application.put_env(:my_app, MyApp.Repo, hostname: "1.2.3.4"), then trigger new connections by briefly setting pool_size: 0 and back, or by using Repo.checkout/2 with a custom connection module that reads the IP at checkout time.:inet.getaddr(hostname, :inet) from the pool process (via :observer or Process.whereis/1) to see the cached address.Which adapter and Erlang/OTP version are you using? Postgrex on OTP 26+ can leverage :inet_res.set_option(:timeout, ms) per connection if you supply a custom connection module; MyXQL and TDS do not currently expose that hook.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.