This package allows you to take control of DNS resolution behavior through configurable multi-resolver strategies.
Why you'd want multiple resolvers: Redundancy (primary resolver failure doesn't cascade into total DNS outage). Performance (concurrent queries across resolvers, returning fastest response). Security (consensus validation across independent resolvers mitigates poisoning and MITM attacks). Integrity (cross-resolver validation detects poisoning, cache corruption, and configuration drift before propagation).
Most OS-level DNS stacks already support multiple resolvers, but they don't use them in parallel, they typically try the first, then fail over in sequence (which can be slow if the first resolver hangs). In high-throughput systems where single-digit millisecond DNS latency affects tail latencies and resolver failures propagate into cascading outages, you need deterministic multi-resolver behavior.
This package provides a DialContext implementation that plugs directly into HTTP transports, gRPC clients, or any custom connection pools expecting net.Dialer.
Built on miekg/dns, dnsdialer implements the same DialContext signature as net.Dialer, making it a drop-in replacement for any Go code that accepts a custom dialer (HTTP clients, gRPC, etc.).
The only difference: instead of using your system DNS resolver, it queries multiple DNS servers using your chosen strategy.
Queries all servers simultaneously and returns the first successful response. Minimizes latency by leveraging the fastest available server.
Queries servers sequentially in order, providing reliability through ordered failover.
Requires a minimum number of servers to agree on the response. Improves security by detecting inconsistencies or DNS poisoning.
Queries all servers and detects discrepancies, calling a user-provided callback when differences are found. Useful for monitoring DNS server integrity.
.png)
