HttpRequest is sent without an explicit timeout
ID |
apex.performance.http_request_timeout |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Performance |
Language |
Apex |
Rationale
The default timeout is 10 seconds and the transaction is allowed 120 seconds of callout time in total, so a slow remote system quietly spends the budget that every other callout in the same transaction needs: the first call waits, the second waits, and the transaction dies on the cumulative limit rather than on anything the remote system reported. Setting the value explicitly also states the contract - it is the difference between "this call may take up to 20 seconds" and nobody having thought about it, which matters most in a trigger, where the user is sitting in front of the save.
The following code illustrates the pattern detected by this rule:
public class BillingGateway {
// FLAGGED: HttpRequest is sent without an explicit timeout
public HttpResponse fetchInvoices() {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Billing_API/invoices');
req.setMethod('GET');
Http http = new Http();
return http.send(req);
}
// FLAGGED: HttpRequest is sent without an explicit timeout
public HttpResponse postInvoice(String body) {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Billing_API/invoices');
req.setMethod('POST');
req.setBody(body);
return new Http().send(req);
}
public HttpResponse fetchInvoicesBounded() {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Billing_API/invoices');
req.setMethod('GET');
req.setTimeout(20000);
Http http = new Http();
return http.send(req);
}
public String describe() {
return 'no callout here';
}
}
Remediation
Call req.setTimeout(milliseconds) with a value the caller can actually wait for, and size it against the number of callouts the transaction makes: the per-transaction budget is 120 seconds for all of them together. Where the remote system is genuinely slow, move the call out of the user’s transaction into a Queueable that implements Database.AllowsCallouts.