Laravel API Integration: Stop Retrying Permanent Failures

๐Ÿ“– 2 minutes read

When integrating with external APIs in Laravel, catching generic exceptions and retrying blindly wastes queue resources. Here’s a better approach: parse error responses and throw domain-specific exceptions.

The Problem

Your queue job calls an API. Sometimes it returns 500 Internal Server Error (temporary). Sometimes it returns 400 Bad Request - Invalid Resource ID (permanent config error). If you catch both with a generic exception, the queue retries forever even for permanent failures.

try {
    $data = $this->apiClient->fetchResource($resourceId);
} catch (ApiException $exception) {
    // Generic catch = queue retries uselessly for config errors
    throw $exception;
}

The Solution

Parse the API error response and throw appropriate exceptions:

try {
    $data = $this->apiClient->fetchResource($resourceId);
} catch (ApiException $exception) {
    $errorCode = json_decode(
        (string)$exception->getPrevious()?->getResponse()->getBody(),
        true
    )['error'] ?? null;

    if ($errorCode === 'INTERNAL_SERVER_ERROR') {
        // Temporary failure - queue should retry
        throw new TemporarilyUnavailableException(
            'Cannot fetch data',
            500,
            $exception
        );
    }

    if ($errorCode === 'INVALID_RESOURCE_ID') {
        // Permanent config error - stop retrying immediately
        throw new InvalidMappingException(
            $this->getResourceMapping($resourceId),
            previous: $exception
        );
    }

    // Unknown error - rethrow original
    throw $exception;
}

Why This Works

Different exception types let your queue orchestrator handle them appropriately:

  • TemporarilyUnavailableException โ€” Queue retries with backoff (API might recover)
  • InvalidMappingException โ€” Queue deletes job immediately (config needs manual fix)
  • Generic exceptions โ€” Default retry behavior

In one real-world case, this pattern stopped ~20,900 useless retry attempts for permanent mapping errors, freeing queue resources immediately.

Key Takeaway

Don’t treat all API failures the same. Parse error responses, throw specific exceptions, and let your queue orchestrator make smart retry decisions.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *