box-node-sdk

Configuration

Retry Strategy

Overview

The SDK ships with a built-in retry strategy (BoxRetryStrategy) that implements the RetryStrategy interface. The BoxNetworkClient, which serves as the default network client, uses this strategy to automatically retry failed API requests with exponential backoff.

The retry strategy exposes two methods:

Default Configuration

Parameter Default Description
maxAttempts 5 Maximum number of retry attempts for HTTP error responses (status 4xx/5xx).
retryBaseInterval 1 (second) Base interval used in the exponential backoff calculation.
retryRandomizationFactor 0.5 Jitter factor applied to the backoff delay. The actual delay is multiplied by a random value between 1 - factor and 1 + factor.
maxRetriesOnException 2 Maximum number of retries for network-level exceptions (connection failures, timeouts). These are tracked by a separate counter from HTTP error retries.

Retry Decision Flow

The following diagram shows how BoxRetryStrategy.shouldRetry decides whether to retry a request:

                    shouldRetry(fetchOptions, fetchResponse, attemptNumber)
                                        |
                                        v
                             +-----------------------+
                             | status == 0           |     Yes
                             | (network exception)?  |----------> attemptNumber <= maxRetriesOnException?
                             +-----------------------+               |            |
                                        | No                        Yes          No
                                        v                            |            |
                             +-----------------------+           [RETRY]      [NO RETRY]
                             | attemptNumber >=      |
                             | maxAttempts?          |
                             +-----------------------+
                                  |            |
                                 Yes          No
                                  |            |
                             [NO RETRY]        v
                             +-----------------------+
                             | status == 202 AND     |     Yes
                             | Retry-After header?   |----------> [RETRY]
                             +-----------------------+
                                        | No
                                        v
                             +-----------------------+
                             | status >= 500         |     Yes
                             | (server error)?       |----------> [RETRY]
                             +-----------------------+
                                        | No
                                        v
                             +-----------------------+
                             | status == 429         |     Yes
                             | (rate limited)?       |----------> [RETRY]
                             +-----------------------+
                                        | No
                                        v
                             +-----------------------+
                             | status == 401 AND     |     Yes
                             | auth available?       |----------> Refresh token, then [RETRY]
                             +-----------------------+
                                        | No
                                        v
                                   [NO RETRY]

Exponential Backoff Algorithm

When the response does not include a Retry-After header, the retry delay is computed using exponential backoff with randomized jitter:

delay = 2^attemptNumber * retryBaseInterval * random(1 - factor, 1 + factor)

Where:

Example Delays (with default settings)

Attempt Base Delay Min Delay (factor=0.5) Max Delay (factor=0.5)
1 2s 1.0s 3.0s
2 4s 2.0s 6.0s
3 8s 4.0s 12.0s
4 16s 8.0s 24.0s

Retry-After Header

When the server includes a Retry-After header in the response, the SDK uses the header value directly as the delay in seconds instead of computing an exponential backoff delay. This applies to any retryable response that includes the header, including:

The header value is parsed as a floating-point number representing seconds.

Network Exception Handling

Network-level failures (connection refused, DNS resolution errors, timeouts, TLS errors) are represented internally as responses with status 0. These exceptions are tracked by a separate counter (maxRetriesOnException, default 2) from the regular HTTP error retry counter (maxAttempts).

This means:

Customizing Retry Parameters

You can customize all retry parameters by initializing BoxRetryStrategy with the desired values and passing it to NetworkSession:

const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
  retryStrategy: new BoxRetryStrategy({
    maxAttempts: 3,
    retryBaseInterval: 2,
    retryRandomizationFactor: 0.3,
    maxRetriesOnException: 1,
  }),
});
const client = new BoxClient({ auth, networkSession });

Custom Retry Strategy

You can implement your own retry strategy by implementing the RetryStrategy interface and overriding the shouldRetry and retryAfter methods:

class CustomRetryStrategy implements RetryStrategy {
  async shouldRetry(
    fetchOptions: FetchOptions,
    fetchResponse: FetchResponse,
    attemptNumber: number,
  ): Promise<boolean> {
    return fetchResponse.status >= 500 && attemptNumber < 3;
  }

  retryAfter(
    fetchOptions: FetchOptions,
    fetchResponse: FetchResponse,
    attemptNumber: number,
  ): number {
    return 1.0;
  }
}

const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
  retryStrategy: new CustomRetryStrategy(),
});
const client = new BoxClient({ auth, networkSession });

Timeouts

You can configure request timeout using timeoutConfig on NetworkSession. timeoutMs is in milliseconds and applies to each HTTP request attempt.

const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
  timeoutConfig: { timeoutMs: 30000 },
});
const client = new BoxClient({ auth, networkSession });

How timeout handling works: