How to change default timeout of Http Client in Laravel
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Mastering HTTP Timeouts in Laravel: A Deep Dive into Client Configuration
As senior developers working with Laravel, we frequently interact with external APIs, and managing request timeouts is crucial for building robust, resilient applications. The default timeout of 30 seconds for the `Illuminate\Http\Client` can sometimes be too permissive or, conversely, too restrictive depending on the service you are interacting with.
This post addresses a common challenge: how to set a global default timeout without inadvertently causing side effects when chaining multiple HTTP requests within a single request lifecycle. We will explore why initial attempts might fail and establish the most practical patterns for configuring your HTTP client in Laravel.
## The Default Behavior vs. Dynamic Configuration
By default, when you use the static `Http` facade in Laravel, you are interacting with an instance managed by the service container. While you can override settings on a per-call basis using methods like `timeout(5)`, applying a global default requires configuring the underlying factory that creates these instances.
The initial approach often involves binding a custom factory:
```php
use Illuminate\Http\Client\Factory;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(Factory::class, static function () {
return new Factory()->withOptions(['timeout' => 5]);
});
}
}
```
While this successfully sets the default timeout for *newly created* instances via the factory, as you discovered, it can lead to unexpected behavior when chaining requests sequentially. The issue arises because subsequent calls using the static facade might still interact with an existing context or cached configuration, leading to the ambiguity you observed between separate API calls.
## Why Sequential Calls Cause Problems
The problem occurs when you mix instantiation methods. When you use `Http::...` repeatedly, Laravel manages a shared context. If one operation implicitly relies on an instance created earlier (even indirectly), changing the default for future independent operations becomes difficult without explicitly forcing a new context.
Consider your scenario where you need two completely separate API calls:
```php
// Attempting to use the facade multiple times
$response1 = Http::baseUrl('www.storageservice.com')->attach('document', 'file_contents', 'document.pdf')->post('/upload');
// If $response2 inherits context, it might behave unexpectedly
$response2 = Http::baseUrl('www.numbergenerator.com')->post('/generate/number');
```
The core issue is that the static facade masks the precise instance management. To ensure true isolation and predictable configuration for every single external callâespecially when dealing with varied servicesâwe need to prioritize explicit instantiation.
## The Best Practice: Explicit Instantiation for Control
For maximum control, especially when timeouts or other client settings are critical and need to be isolated per operation, the recommended approach is to always instantiate a fresh HTTP client whenever you begin an independent request. This aligns perfectly with the principle of clear separation in application logic, which is fundamental to good Laravel development, as emphasized by resources like [laravelcompany.com](https://laravelcompany.com).
By using `Http::new()`, you guarantee that every request starts with a fresh client instance, inheriting only the settings explicitly defined for that specific call. This removes any ambiguity caused by global defaults or shared service container bindings.
### Implementing Isolated Timeouts
To achieve your goal of setting a 5-second timeout reliably without side effects, use `Http::new()` for each independent request:
```php
use Illuminate\Support\Facades\Http;
// Request 1 with a specific 5-second timeout
$response1 = Http::timeout(5)->baseUrl('www.storageservice.com')
->attach('document', 'file_contents', 'document.pdf')
->post('/upload');
// Request 2, completely independent, with its own timeout setting
$response2 = Http::timeout(5)->baseUrl('www.numbergenerator.com')
->post('/generate/number');
// Now $response1 and $response2 are completely isolated and predictable.
```
Notice how we apply `->timeout(5)` directly to the instance being created via `Http::new()`. This provides explicit control over that specific operation, ensuring that the timeout applies exactly where you intend it to, regardless of any global service provider configuration.
## Conclusion
While binding factories is excellent for setting application-wide defaults, for dynamic operations like HTTP requests where isolation and predictability are paramount, **explicit instantiation (`Http::new()`) remains the most robust pattern.** It gives you surgical control over each request's behavior. By adopting this approach, you eliminate the ambiguity between shared service container settings and ensure that your HTTP client configurations are explicit, readable, and entirely independent, leading to more stable and maintainable code in your Laravel applications.