Handle Token Refresh Safely in Concurrent API Calls

Prevent multiple token refreshes when parallel API calls fail — learn how to design a shared promise-based refresh mechanism.

advancedAsync and promisesjavascriptauthenticationpromisesapitoken refresh
Published: 11/12/2025
Updated: 11/12/2025

Advertisement

Question

You have multiple API requests that fail with a 401 Unauthorized error at the same time.
How can you ensure only one refresh request runs, while other requests wait for it to complete?


Explanation

This is a race condition in authentication logic.
If each failed request triggers a token refresh independently, you’ll flood your API.

We fix this by sharing one refresh promise globally.


Implementation

let refreshPromise = null;

async function refreshTokenOnce() {
  if (!refreshPromise) {
    refreshPromise = fetch('/auth/refresh')
      .then((res) => res.json())
      .finally(() => (refreshPromise = null));
  }
  return refreshPromise;
}

async function fetchWithAuth(url, options) {
  const res = await fetch(url, options);
  if (res.status === 401) {
    const newToken = await refreshTokenOnce();
    return fetch(url, {
      ...options,
      headers: { Authorization: `Bearer ${newToken.accessToken}` },
    });
  }
  return res;
}

Visualization

sequenceDiagram participant A as API Request 1 participant B as API Request 2 participant R as Refresh Token Call A->>R: 401 → Triggers refresh B->>R: Waits for same promise R-->>A: New Token Returned R-->>B: Same Token Used

Summary

✅ Prevents redundant token refresh
✅ Keeps requests synchronized
✅ Works with Axios interceptors or fetch
✅ Real-world production pattern for any token-based app

Frequently Asked Questions

Why do multiple refresh calls happen?

When parallel API calls get 401s, each tries to refresh the token — unless you share a single refresh promise.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement