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
Retry attempts
Failed requests are retried up to 2 times by default (3 total attempts).
Retryable conditions
The following errors trigger automatic retries:
Connection errors (network failures)
408 Request Timeout
409 Conflict
429 Rate Limit
≥500 Internal Server Error
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
});
Override retry behavior for specific requests: await client . zones . get (
{ zone_id: '023e105f4ecef8ad9ca31a8372d0c353' },
{
maxRetries: 5 , // Retry this request up to 5 times
}
);
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
Attempt Base Delay With Jitter (approx) 1st retry 0.5s 0.375s - 0.5s 2nd retry 1.0s 0.75s - 1.0s 3rd retry 2.0s 1.5s - 2.0s 4th retry 4.0s 3.0s - 4.0s 5th retry 8.0s 6.0s - 8.0s
The SDK respects server-provided retry timing:
retry-after-ms
retry-after (seconds)
retry-after (HTTP date)
x-should-retry
// 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
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 });
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 });
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 ;
}
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 ;
}
}
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 ;
}