Skip to main content
The Cloudflare SDK provides configurable timeout and retry mechanisms to handle network issues and transient failures.

Timeout configuration

Requests time out after 60 seconds (60,000 milliseconds) by default.

Global timeout

Set a default timeout for all requests:
import Cloudflare from 'cloudflare';

const client = new Cloudflare({
  timeout: 20 * 1000, // 20 seconds
});

Per-request timeout

Override the timeout for individual requests:
const zone = await client.zones.edit(
  { zone_id: '023e105f4ecef8ad9ca31a8372d0c353' },
  {
    timeout: 5 * 1000, // 5 seconds
  }
);
Timeout values are specified in milliseconds. The default timeout is 60000 (1 minute).

Timeout errors

When a request times out, the SDK throws APIConnectionTimeoutError:
import Cloudflare from 'cloudflare';

const client = new Cloudflare();

try {
  const zone = await client.zones.get(
    { zone_id: '023e105f4ecef8ad9ca31a8372d0c353' },
    { timeout: 1000 } // Very short timeout
  );
} catch (err) {
  if (err instanceof Cloudflare.APIConnectionTimeoutError) {
    console.error('Request timed out');
    // Retry with longer timeout or implement backoff
  }
  throw err;
}

Retry behavior

The SDK automatically retries failed requests with exponential backoff.

Default retry policy

1

Retry attempts

Failed requests are retried up to 2 times by default (3 total attempts).
2

Retryable conditions

The following errors trigger automatic retries:
  • Connection errors (network failures)
  • 408 Request Timeout
  • 409 Conflict
  • 429 Rate Limit
  • ≥500 Internal Server Error
3

Exponential backoff

Retry delays increase exponentially:
  • Initial delay: 0.5 seconds
  • Maximum delay: 8 seconds
  • Jitter: Up to 25% variance

Configuring retries

Set the default retry behavior for all requests:
const client = new Cloudflare({
  maxRetries: 0, // Disable retries
});

const client = new Cloudflare({
  maxRetries: 5, // Retry up to 5 times
});
maxRetries
number
default:"2"
Maximum number of retry attempts. Set to 0 to disable retries.

Retry timing

The SDK uses exponential backoff with jitter to calculate retry delays:
// Retry delay calculation (internal)
function calculateRetryDelay(retryCount: number): number {
  const initialDelay = 0.5; // seconds
  const maxDelay = 8.0;     // seconds
  
  // Exponential backoff
  const delay = Math.min(
    initialDelay * Math.pow(2, retryCount),
    maxDelay
  );
  
  // Add jitter (up to 25% variance)
  const jitter = 1 - Math.random() * 0.25;
  
  return delay * jitter * 1000; // Convert to milliseconds
}

Example retry timeline

AttemptBase DelayWith Jitter (approx)
1st retry0.5s0.375s - 0.5s
2nd retry1.0s0.75s - 1.0s
3rd retry2.0s1.5s - 2.0s
4th retry4.0s3.0s - 4.0s
5th retry8.0s6.0s - 8.0s

Retry headers

The SDK respects server-provided retry timing:
// Server response includes:
// retry-after-ms: 5000

// SDK waits 5000ms before retrying
Server-provided retry delays are only used if they fall within 0-60 seconds. Otherwise, the default exponential backoff applies.

Timeout and retry interaction

Timeouts apply to each individual request attempt, not the total time including retries:
const client = new Cloudflare({
  timeout: 10 * 1000,  // 10 second timeout per attempt
  maxRetries: 2,        // 2 retries (3 total attempts)
});

// Worst case: 3 attempts × 10s timeout + retry delays
// Could take 30+ seconds total before final failure

Managing total time

To limit the total time including retries, use AbortSignal:
const controller = new AbortController();

// Abort after 30 seconds total
setTimeout(() => controller.abort(), 30 * 1000);

try {
  const zone = await client.zones.get(
    { zone_id: '023e105f4ecef8ad9ca31a8372d0c353' },
    { signal: controller.signal }
  );
} catch (err) {
  if (err instanceof Cloudflare.APIUserAbortError) {
    console.error('Request aborted after timeout');
  }
  throw err;
}

Request cancellation

Cancel in-flight requests using AbortSignal:
const controller = new AbortController();

const promise = client.zones.list({
  signal: controller.signal,
});

// Cancel the request
controller.abort();

try {
  await promise;
} catch (err) {
  if (err instanceof Cloudflare.APIUserAbortError) {
    console.log('Request was cancelled');
  }
}
Cancelling a request does not guarantee the operation won’t complete on the server. Use idempotent operations when possible.

Best practices

1

Set appropriate timeouts

Choose timeout values based on expected operation duration:
// Quick metadata fetch
client.zones.get(params, { timeout: 5000 });

// Large data export
client.logs.download(params, { timeout: 120000 });
2

Use retries for transient failures

Enable retries for operations that can safely be retried:
// Safe to retry (idempotent)
client.zones.list({ maxRetries: 3 });

// Not safe to retry (non-idempotent)
client.zones.create(params, { maxRetries: 0 });
3

Monitor timeout errors

Track timeout patterns to identify issues:
try {
  await client.zones.get(params);
} catch (err) {
  if (err instanceof Cloudflare.APIConnectionTimeoutError) {
    // Log timeout for monitoring
    console.error('Timeout occurred', {
      endpoint: 'zones.get',
      timestamp: new Date(),
    });
  }
  throw err;
}
4

Implement circuit breakers

Prevent cascading failures with circuit breaker patterns:
let failureCount = 0;
const MAX_FAILURES = 5;

async function safeApiCall() {
  if (failureCount >= MAX_FAILURES) {
    throw new Error('Circuit breaker open');
  }
  
  try {
    const result = await client.zones.list();
    failureCount = 0; // Reset on success
    return result;
  } catch (err) {
    failureCount++;
    throw err;
  }
}
5

Handle rate limits gracefully

Respect 429 responses and retry headers:
try {
  await client.zones.create(params);
} catch (err) {
  if (err instanceof Cloudflare.RateLimitError) {
    // SDK already retried automatically
    console.error('Rate limit exceeded after retries');
    // Consider implementing additional backoff
  }
  throw err;
}

Configuration reference

Complete ClientOptions for timeouts and retries:
interface ClientOptions {
  /**
   * Maximum time in milliseconds to wait for a response
   * @default 60000 (1 minute)
   */
  timeout?: number;
  
  /**
   * Maximum number of retry attempts
   * @default 2
   */
  maxRetries?: number;
  
  /**
   * HTTP agent for connection pooling
   * @default Automatically created in Node.js
   */
  httpAgent?: Agent;
}

Per-request options

interface RequestOptions {
  /** Override timeout for this request */
  timeout?: number;
  
  /** Override maxRetries for this request */
  maxRetries?: number;
  
  /** AbortSignal for request cancellation */
  signal?: AbortSignal;
  
  /** Custom HTTP agent for this request */
  httpAgent?: Agent;
}

Build docs developers (and LLMs) love