KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: 4D.HTTPagent: Utility Method to Implement a Retry with Backoff
PRODUCT: 4D | VERSION: 21 | PLATFORM: Mac & Win
Published On: December 19, 2025
The utility project method effectively wraps HTTPAgent requests, performs retries with increasing delays (1s, 2s, 4s).

Util_sendRequestWithRetry
#DECLARE($url : Text; $method : Text; $body : Variant; $headers : Object) -> $response : Object

var $agent : 4D.HTTPAgent
$agent:=4D.HTTPAgent.new()

var $baseOptions : Object
$baseOptions:=New object
$baseOptions.agent:=$agent
$baseOptions.method:=$method
If ($body#Null)
    $baseOptions.body:=$body
End if
If ($headers#Null)
    $baseOptions.headers:=$headers
End if

var $maxRetries : Integer:=3
var $backoff : Integer:=1000 // ms

For ($retry; 0; $maxRetries)
    var $options : Object
    $options:=OB Copy($baseOptions)

    var $request : 4D.HTTPRequest
    $request:=4D.HTTPRequest.new($url; $options)

    $response:=$request.wait(30) // Added 30s timeout for safety

    If ($response=Null)
        If ($retry<$maxRetries)
            DELAY PROCESS(Current process; $backoff / 60)
            $backoff:=$backoff*2
        End if
    Else
        Case of
            : ($response.status>=200) & ($response.status<300)
                return $response
            : ($response.status#0) & ($response.status#408) & \
                ($response.status#429) & ($response.status<500)
                return $response
        End case
        If ($retry<$maxRetries)
            DELAY PROCESS(Current process; $backoff / 60)
            $backoff:=$backoff*2
        End if
    End if
End for



Test example:

var $response : Object
$response:=Util_sendRequestWithRetry("https://api.example.com"; "GET"; Null; Null)


  • Body = Null: Because it's a GET request. GET should not have a request body (per HTTP specs, RFC 9110). Any body would be ignored or cause issues.

  • Headers = Null: No custom headers are needed for this simple test (e.g., no auth token or Content-Type).

  • When required, don't use Null in case body for POST/PUT, and headers for auth, Content-Type, etc...