Category: PHP

  • Guzzle’s Default Timeout Is Infinite — And That’s a Problem

    Guzzle’s Default Timeout Is Infinite — And That’s a Problem

    Here’s something that might surprise you: Guzzle’s default timeout is zero — which means wait forever.

    That’s right. If you create an HTTP client without setting a timeout, your application will happily sit there for minutes (or longer) waiting for a response that may never come. In a web request, your users see a spinner. In a queue job, you burn through worker capacity while the job just… hangs.

    I ran into this recently when debugging why queue workers kept dying. The root cause? An external API was occasionally slow to respond, and the HTTP client had no timeout configured. The job would hang until the queue worker’s own timeout killed it — by which point it had already wasted 5+ minutes of processing capacity.

    The fix was embarrassingly simple:

    use GuzzleHttp\Client;
    
    $client = new Client([
        'base_uri' => 'https://api.example.com/',
        'timeout' => 30,
        'connect_timeout' => 10,
    ]);
    

    Two options to know:

    • timeout — Total seconds to wait for a response (including transfer time)
    • connect_timeout — Seconds to wait just for the TCP connection to establish

    If you’re configuring HTTP clients in a Laravel service provider (which you should be), set these defaults at the client level:

    $this->app->bind(ApiClient::class, function ($app) {
        $http = new Client([
            'base_uri' => config('services.vendor.url'),
            'timeout' => 30,
            'connect_timeout' => 10,
        ]);
    
        return new ApiClient($http);
    });
    

    A quick audit tip: search your codebase for new Client( or wherever you instantiate Guzzle clients. If you don’t see timeout in the options array, you’ve got a ticking time bomb. Especially in queue jobs, where a hanging HTTP request can cascade into MaxAttemptsExceededException and fill your failed jobs table.

    Rule of thumb: 30 seconds for most API calls, 10 seconds for connection timeout. Adjust based on what you know about the external service, but never leave it at zero.