Axios Secondary API Host Fallback Techniques
Implementing a secondary host fallback strategy in Axios ensures high availability for applications by redirecting traffic to backup servers when the primary host is unreachable or returns server errors. This article covers practical techniques to achieve automated failover using Axios response interceptors, custom client wrappers, and specialized retry libraries, along with key considerations like request idempotency and infinite loop prevention.
1. Axios Response Interceptors
Using Axios interceptors is the most common and native way to handle
host fallbacks. When a request fails due to a network error, timeout, or
specific HTTP status code (such as 502, 503, or 504), the response
interceptor catches the error, updates the target URL or
baseURL to the secondary host, and replays the request.
import axios from 'axios';
const PRIMARY_HOST = 'https://api.primary.example.com';
const SECONDARY_HOST = 'https://api.secondary.example.com';
const apiClient = axios.create({
baseURL: PRIMARY_HOST,
timeout: 5000,
});
apiClient.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// Check if the request has already failed over
if (originalRequest && !originalRequest._isRetry) {
const isNetworkError = !error.response;
const isServerError = error.response && error.response.status >= 500;
if (isNetworkError || isServerError) {
originalRequest._isRetry = true;
// Swap to the secondary host
originalRequest.baseURL = SECONDARY_HOST;
// Re-execute the request with the updated config
return apiClient(originalRequest);
}
}
return Promise.reject(error);
}
);
export default apiClient;2. Using
axios-retry with Dynamic URL Configuration
The axios-retry library simplifies retry logic and
allows dynamic modification of request parameters on subsequent
attempts.
import axios from 'axios';
import axiosRetry from 'axios-retry';
const PRIMARY_HOST = 'https://api.primary.example.com';
const SECONDARY_HOST = 'https://api.secondary.example.com';
const apiClient = axios.create({
baseURL: PRIMARY_HOST,
timeout: 5000,
});
axiosRetry(apiClient, {
retries: 1,
retryCondition: (error) => {
return axiosRetry.isNetworkOrIdempotentRequestError(error) ||
(error.response && error.response.status >= 500);
},
onRetry: (retryCount, error, requestConfig) => {
// Switch to the fallback host on retry
requestConfig.baseURL = SECONDARY_HOST;
},
retryDelay: () => 0, // Failover immediately or apply backoff
});
export default apiClient;3. Custom API Client Wrapper
A service wrapper pattern encapsulates primary and secondary Axios instances, giving full programmatic control over fallback behavior, circuit breaking, and telemetry logging without mutating raw Axios configs.
import axios from 'axios';
class ResilientApiClient {
constructor(primaryUrl, secondaryUrl) {
this.primaryClient = axios.create({ baseURL: primaryUrl, timeout: 5000 });
this.secondaryClient = axios.create({ baseURL: secondaryUrl, timeout: 5000 });
}
async request(config) {
try {
return await this.primaryClient(config);
} catch (error) {
if (this.shouldFallback(error)) {
return await this.secondaryClient(config);
}
throw error;
}
}
shouldFallback(error) {
return !error.response || error.response.status >= 500;
}
get(url, config) {
return this.request({ ...config, method: 'get', url });
}
post(url, data, config) {
return this.request({ ...config, method: 'post', url, data });
}
}
export const api = new ResilientApiClient(
'https://api.primary.example.com',
'https://api.secondary.example.com'
);Key Implementation Considerations
- Idempotency Safeguards: Automatically retrying
non-idempotent HTTP methods (such as
POSTorPATCH) can lead to duplicate transactions if the primary server processed the request but failed to return a response. Ensure fallback retry logic is restricted to idempotent methods (GET,PUT,DELETE,HEAD) or uses unique idempotency keys. - Loop Prevention: Always flag modified request
configs (e.g., using
_isRetry = true) to prevent infinite recursion if the secondary host is also offline. - Host Health Tracking: Instead of failing over on every single request when the primary host is down, implement a circuit breaker pattern or temporary state variable to route subsequent requests directly to the secondary host until the primary recovers.