SYS://VISION.ACTIVE
VIEWPORT.01
LAT 28.0222° N
SIGNAL.NOMINAL
VISION Loading
Back to Blog

Error Handling Architecture: Graceful Degradation

Shane Barron

Shane Barron

Laravel Developer & AI Integration Specialist

Failures Are Inevitable

Systems fail. Networks go down, databases crash, third-party services become unavailable. Good architecture assumes failures and designs for graceful degradation.

Circuit Breaker Pattern

class CircuitBreaker
{
    private int $failureCount = 0;
    private int $threshold = 5;
    private ?Carbon $openedAt = null;

    public function call(callable $action): mixed
    {
        if ($this->isOpen()) {
            throw new CircuitOpenException();
        }

        try {
            $result = $action();
            $this->reset();
            return $result;
        } catch (Exception $e) {
            $this->recordFailure();
            throw $e;
        }
    }

    private function isOpen(): bool
    {
        if ($this->openedAt === null) {
            return false;
        }

        // Half-open after timeout
        if ($this->openedAt->addMinutes(1)->isPast()) {
            return false;
        }

        return true;
    }

    private function recordFailure(): void
    {
        $this->failureCount++;
        if ($this->failureCount >= $this->threshold) {
            $this->openedAt = now();
        }
    }
}

Retry with Backoff

class RetryHandler
{
    public function withRetry(
        callable $action,
        int $maxAttempts = 3,
        int $baseDelay = 1000
    ): mixed {
        $attempt = 0;

        while (true) {
            try {
                return $action();
            } catch (RetryableException $e) {
                $attempt++;
                if ($attempt >= $maxAttempts) {
                    throw $e;
                }

                $delay = $baseDelay * pow(2, $attempt);
                usleep($delay * 1000);
            }
        }
    }
}

Fallback Strategies

class ProductService
{
    public function get(int $id): Product
    {
        try {
            return $this->primaryService->get($id);
        } catch (ServiceUnavailableException $e) {
            // Fallback to cache
            if ($cached = Cache::get("product_{$id}")) {
                return $cached;
            }

            // Fallback to degraded response
            return Product::placeholder($id);
        }
    }
}

Bulkhead Pattern

// Isolate failures with separate connection pools
class ServiceConnections
{
    public function forPayments(): Client
    {
        return new Client(['pool' => 'payments', 'max' => 10]);
    }

    public function forInventory(): Client
    {
        return new Client(['pool' => 'inventory', 'max' => 5]);
    }

    // Payment failures don't exhaust inventory connections
}

Conclusion

Design for failure with circuit breakers, retries with backoff, fallbacks, and isolation. The goal isn't to prevent all failures—it's to handle them gracefully and recover automatically.

Share this article
Shane Barron

Shane Barron

Strategic Technology Architect with 40 years of experience building production systems. Specializing in Laravel, AI integration, and enterprise architecture.

Need Help With Your Project?

I respond to all inquiries within 24 hours. Let's discuss how I can help build your production-ready system.

Get In Touch