Guide
Choosing Between Node.js Built‑in fetch and Axios for HTTP Requests
Guidance on selecting Node.js fetch or axios based on LTS version, features, and maintenance overhead.
Published by Tasadduq Burney
05 Jan 2026, 12:08 UTC
3 min148K views0

Decision and constraints
For new internal services running on Node.js 20+ LTS, prefer the built‑in fetch global when you need simple request/response handling or streaming via Web Streams. Keep axios when you require automatic retries, request/response interceptors, or must support Node.js versions older than 18 where the global fetch is unavailable or incomplete.
Option comparison
| Feature | Built‑in fetch | Axios |
|---|---|---|
| Availability | Node ≥18 (stable in ≥20) | All LTS versions via npm |
| Timeout mechanism | AbortController + setTimeout | timeout config option |
| Interceptors | None (manual wrapping) | Built‑in request/response interceptors |
| Streaming model | Web Streams (response.body) | Node.js streams |
| Dependency | None | axios package |
Trade‑offs
- Built‑in fetch: reduces supply‑chain risk, lower startup cost, aligns with the Fetch standard, but requires you to implement error classification, retry logic, and timeout handling yourself.
- Axios: provides convenient defaults (timeout, interceptors, automatic JSON transformation) and works on older Node versions, at the cost of an extra dependency, potential version drift, and a non‑standard streaming API.
Concrete implementation
Built‑in fetch helper
// fetchHelper.js
// Run with Node ≥20 (global fetch and AbortController are available)
export async function fetchJson(url, { timeoutMs = 5000 } = {}) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeout);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (err) {
clearTimeout(timeout);
if (err.name === 'AbortError') {
throw new Error(`Request timed out after ${timeoutMs}ms`);
}
throw err;
}
}
Example usage (replace http://localhost:3000/test with your endpoint):
// testFetch.js
import { fetchJson } from './fetchHelper.js';
fetchJson('http://localhost:3000/test')
.then(data => console.log('Fetched:', data))
.catch(err => console.error('Error:', err.message));
Axios equivalent
// axiosHelper.js
// Run after: npm install axios
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:3000',
timeout: 5000,
});
api.interceptors.request.use(config => {
config.headers.Authorization = `Bearer ${process.env.TOKEN || ''}`;
return config;
});
export async function getJson(path) {
const { data } = await api.get(path);
return data;
}
Example usage:
// testAxios.js
import { getJson } from './axiosHelper.js';
getJson('/test')
.then(data => console.log('Fetched:', data))
.catch(err => console.error('Error:', err.message));
Validation steps
- Start a minimal test server (e.g., using
node:http) that returns a known JSON payload on/testand can optionally delay responses to test timeouts. - Run the fetch helper against
http://localhost:/testand confirm it returns the payload or throws a timeout error after the configured period. - Run the axios helper against the same endpoint and verify identical success/error behavior.
- Measure cold‑start overhead: compare startup time of a script that only uses
fetchversus one thatrequire('axios')(e.g.,time node -e "require('axios')"vstime node -e "").
Limitations and practical checks
- Fetch uses Web Streams; if your existing pipeline expects Node.js streams, convert via
stream.Readable.fromWeb(response.body)or manually pipe. - Timeout with fetch relies on
AbortController; ensure you clear the timeout to avoid unintended aborts. - When using axios, pin the version in your lockfile to prevent unexpected breaking changes.
- To verify streaming, fetch a large payload and pipe
response.bodyto a file or another stream, confirming data arrives incrementally.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.