Configure DNS Lookup Options in Axios on Node.js

Configuring DNS lookup in Axios on Node.js allows developers to fine-tune network performance, force specific IP versions (IPv4 or IPv6), bypass system-level resolution limitations, and implement custom DNS caching. Because Axios relies on the underlying Node.js http and https modules for networking, DNS options are configured by attaching custom http.Agent and https.Agent instances containing custom lookup functions to your Axios requests.

Understanding DNS Lookup in Node.js and Axios

By default, Node.js uses the operating system's getaddrinfo system call via dns.lookup() for domain resolution. This operates synchronously on the libuv thread pool. Under high network traffic, this can lead to thread pool exhaustion and increased request latency.

To modify this behavior in Axios, you define a custom lookup option within a Node.js Agent and pass it to your Axios instance via the httpAgent and httpsAgent configuration properties.


Forcing IPv4 or IPv6 Resolution

A common use case is forcing Axios to resolve hostnames to IPv4 addresses to avoid timeout issues caused by broken or slow IPv6 routing on specific networks.

const axios = require('axios');
const http = require('http');
const https = require('https');
const dns = require('dns');

// Custom lookup function forcing IPv4
const ipv4Lookup = (hostname, options, callback) => {
  return dns.lookup(hostname, { family: 4, all: false }, callback);
};

// Create custom agents
const httpAgent = new http.Agent({ lookup: ipv4Lookup });
const httpsAgent = new https.Agent({ lookup: ipv4Lookup });

// Create an Axios instance with the agents attached
const apiClient = axios.create({
  httpAgent,
  httpsAgent,
});

async function run() {
  try {
    const response = await apiClient.get('https://example.com');
    console.log(`Status: ${response.status}`);
  } catch (error) {
    console.error('Request failed:', error.message);
  }
}

run();

Using Custom DNS Servers (Asynchronous Resolution)

If you need to query custom nameservers (such as Cloudflare 1.1.1.1 or Google 8.8.8.8) without relying on the OS-level getaddrinfo, use the dns.Resolver class from Node.js:

const axios = require('axios');
const https = require('https');
const { Resolver } = require('dns');

const resolver = new Resolver();
resolver.setServers(['1.1.1.1', '8.8.8.8']); // Set custom DNS servers

// Define custom lookup using the resolver
const customDnsLookup = (hostname, options, callback) => {
  resolver.resolve4(hostname, (err, addresses) => {
    if (err) {
      return callback(err);
    }
    // Return the first resolved IP address and specify IPv4 family
    callback(null, addresses[0], 4);
  });
};

const httpsAgent = new https.Agent({ lookup: customDnsLookup });

const apiClient = axios.create({
  httpsAgent,
});

async function run() {
  const response = await apiClient.get('https://example.com');
  console.log(response.status);
}

run();

Enabling DNS Caching for High-Throughput Applications

Repeated DNS lookups for the same host add unnecessary latency. You can install an in-memory DNS caching library like cacheable-lookup and attach its lookup method to your Axios agents:

npm install cacheable-lookup
const axios = require('axios');
const http = require('http');
const https = require('https');
const CacheableLookup = require('cacheable-lookup');

const cacheable = new CacheableLookup();

// Attach the cache lookup method to HTTP and HTTPS agents
const httpAgent = new http.Agent({ lookup: cacheable.lookup });
const httpsAgent = new https.Agent({ lookup: cacheable.lookup });

const apiClient = axios.create({
  httpAgent,
  httpsAgent,
  timeout: 5000,
});

async function makeRequests() {
  // First call resolves and caches the IP address
  await apiClient.get('https://example.com');

  // Subsequent calls use the cached IP address, bypassing DNS resolution
  await apiClient.get('https://example.com');
}

makeRequests();

Per-Request Configuration

If you do not want to set global agents on an Axios instance, you can supply httpAgent and httpsAgent directly inside the request configuration object:

await axios.get('https://example.com', {
  httpsAgent: new https.Agent({
    lookup: (hostname, options, callback) => {
      dns.lookup(hostname, { hints: dns.ADDRCONFIG }, callback);
    }
  })
});