Skip to main content

A production-grade, asynchronous HTTP client for Python engineered to tolerate downstream service outages, network instability, and latency spikes.

Project description

๐Ÿ›ก๏ธ Resilient HTTP Client

A production-grade, asynchronous HTTP client for Python engineered to tolerate downstream service outages, network instability, and latency spikes. It implements proven resilience patterns including Circuit Breakers, Retry Policies, Fallback Mechanisms, and a Distributed Failure Store to enable reliable service-to-service communication.

Built on top of httpx, the library is designed for modern distributed systems where resilience is a first-class requirement.


๐Ÿš€ Features

  • Circuit Breaker Pattern โ€” Prevents cascading failures using a strict state machine (CLOSED, OPEN, HALF-OPEN).
  • Distributed Failure Store โ€” Share circuit state and failure metrics across workers and service instances.
  • Automatic Retries โ€” Configurable retry budgets with exponential backoff for transient failures.
  • Graceful Fallbacks โ€” Return degraded responses or execute alternative logic instead of surfacing raw exceptions.
  • Fully Asynchronous โ€” Built on httpx for high-concurrency, non-blocking I/O.
  • Pluggable Components โ€” Storage and resilience behavior can be customized to fit different deployment environments.
  • Production Ready โ€” Suitable for microservices, containerized workloads, and distributed deployments.

๐Ÿ“ System Architecture

The following diagram illustrates how the components of resilient-http-client coordinate request delivery, state checking, retries, and fallback execution.

flowchart TD
    classDef main fill:#1E88E5,stroke:#1565C0,stroke-width:2px,color:#fff;
    classDef support fill:#43A047,stroke:#2E7D32,stroke-width:2px,color:#fff;
    classDef store fill:#E53935,stroke:#C62828,stroke-width:2px,color:#fff;

    Client["ResilientHttpClient"]:::main
    CB["CircuitBreaker"]:::main
    Store["FailureStore"]:::store
    Retry["RetryPolicy"]:::support
    Fallback["FallbackHandler"]:::support
    Executor["HttpExecutor (httpx)"]:::support

    Client -->|1. Check state / record metrics| CB
    Client -->|2. Manage retry attempts| Retry
    Client -->|3. Fallback on final error| Fallback
    Client -->|4. Dispatch requests| Executor
    CB -->|Query & persist state / counters| Store

๐Ÿ”„ Circuit Breaker State Machine

The client implements a fully compliant circuit breaker state machine with lazy cooldown transitions and probe request gating.

stateDiagram-v2
    [*] --> Closed : Initial State

    Closed --> Open : failures >= threshold
    Closed --> Closed : success

    Open --> HalfOpen : cooldown expired
    Open --> Open : block requests

    HalfOpen --> Closed : success >= successes_needed
    HalfOpen --> Open : any failure

State Behavior

CLOSED

Requests flow normally.

  • Successful requests reset failure counters.
  • Consecutive failures are tracked.
  • Reaching the configured threshold transitions the circuit to OPEN.

OPEN

Requests fail immediately without contacting the downstream service.

  • Prevents latency amplification and resource exhaustion.
  • Remains open for the configured cooldown period.
  • Automatically transitions to HALF-OPEN after cooldown expires.

HALF-OPEN

Allows a limited number of probe requests.

  • Successful probes close the circuit.
  • Any failed probe immediately reopens the circuit.
  • Prevents unstable services from causing repeated outages.

โšก Quick Start

import asyncio
import redis.asyncio as redis

from resilient_http_client import (
    FailureStore,
    ResilientHttpClient,
)

async def main():
    # Example using Redis-backed storage
    redis_client = redis.Redis(
        host="localhost",
        port=6379,
        decode_responses=True,
    )

    store = FailureStore(
        redis=redis_client,
        service="stripe_payment",
    )

    async with ResilientHttpClient(
        service="stripe_payment",
        store=store,
    ) as client:

        response = await client.request(
            method="POST",
            url="https://api.stripe.com/v1/charges",
            json={
                "amount": 2000,
                "currency": "usd",
            },
        )

        print(response)

if __name__ == "__main__":
    asyncio.run(main())

โš™๏ธ Configuration

Customize resilience behavior through ResilienceConfig.

from resilient_http_client import ResilienceConfig

config = ResilienceConfig(
    failure_threshold=5,
    cooldown=30,
    max_retries=3,
    timeout=5.0,
    half_open_max_calls=1,
    half_open_successes_needed=1,
)

client = ResilientHttpClient(
    service="my-api",
    store=store,
    config=config,
)

Configuration Reference

Parameter Type Default Description
failure_threshold int 5 Consecutive failures required to open the circuit
cooldown int 30 Seconds before an open circuit transitions to half-open
max_retries int 3 Number of retry attempts before failure
timeout float 5.0 Request timeout in seconds
half_open_max_calls int 1 Maximum probe requests allowed while half-open
half_open_successes_needed int 1 Successful probes required to close the circuit

๐Ÿงฉ Components

Circuit Breaker

Prevents repeated requests to unhealthy downstream services.

States:

  • Closed โ€” Requests flow normally.
  • Open โ€” Requests fail immediately.
  • Half-Open โ€” Limited recovery probes are allowed.

Retry Policy

Automatically retries transient failures using configurable exponential backoff.

Typical retry conditions include:

  • HTTP 5xx responses
  • Connection failures
  • Network timeouts

Fallback Handler

Fallbacks are executed when:

  • The circuit is open.
  • Retry attempts are exhausted.
  • A non-retryable failure occurs.

Failure Store

Persists resilience state used by the circuit breaker.

Responsibilities include:

  • Failure counters
  • Circuit state
  • Cooldown timestamps
  • Cross-worker coordination

The library includes a Redis-backed implementation and can be extended with custom storage backends.


๐Ÿ› ๏ธ Project Structure

src/
โ””โ”€โ”€ resilient_http_client/
    โ”œโ”€โ”€ __init__.py
    โ”œโ”€โ”€ client.py
    โ”œโ”€โ”€ circuit_breaker.py
    โ”œโ”€โ”€ config.py
    โ”œโ”€โ”€ failure_store.py
    โ”œโ”€โ”€ fallback.py
    โ”œโ”€โ”€ http.py
    โ”œโ”€โ”€ retry.py
    โ””โ”€โ”€ types.py

tests/
โ”œโ”€โ”€ test_circuit_breaker.py
โ”œโ”€โ”€ test_failure_store.py
โ”œโ”€โ”€ test_fallback.py
โ”œโ”€โ”€ test_flaky_resilience.py
โ”œโ”€โ”€ test_integration.py
โ””โ”€โ”€ test_retry_policy.py

Module Overview

  • ๐Ÿ›ฐ๏ธ client.py โ€” Main orchestration layer.
  • ๐Ÿ”Œ circuit_breaker.py โ€” Circuit breaker state machine.
  • ๐Ÿ—„๏ธ failure_store.py โ€” Distributed state management.
  • ๐Ÿ” retry.py โ€” Retry policy implementation.
  • ๐ŸŽญ fallback.py โ€” Fallback registration and execution.
  • โš™๏ธ config.py โ€” Configuration definitions.
  • ๐Ÿ“˜ types.py โ€” Shared enums and type definitions.
  • ๐ŸŒ http.py โ€” HTTP request execution layer.

๐Ÿงช Running the Tests

Run the full test suite:

uv run pytest

Coverage Includes

  • Failure tracking
  • Circuit opening thresholds
  • Cooldown transitions
  • Half-open probe gating
  • Recovery behavior
  • Retry policies
  • Distributed state persistence
  • Fallback execution paths

๐Ÿ“š Examples

The examples/ directory contains complete demonstrations and integrations.

How to run examples

  1. Start Redis:

    docker compose up -d
    
  2. Run the example:

    PYTHONPATH=. uv run python examples/slack_example.py
    

Available examples:

  • fastapi_integration.py
  • simulate_outage.py
  • slack_example.py
  • stripe_example.py

๐ŸŽฏ Use Cases

  • Service-to-service communication
  • Third-party API integrations
  • Payment gateways
  • Authentication providers
  • Event-driven systems
  • Containerized applications
  • Kubernetes deployments
  • Any environment where downstream dependencies may become unavailable

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ad_tech_inc_resilient_http-0.1.0.tar.gz (368.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ad_tech_inc_resilient_http-0.1.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file ad_tech_inc_resilient_http-0.1.0.tar.gz.

File metadata

File hashes

Hashes for ad_tech_inc_resilient_http-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8693e0e7bf5a195b94aac7dd2a764556234ef515698f61c50a43d6fa328d39da
MD5 a667b4fbc82c91d1801dff3f1177efda
BLAKE2b-256 fc26be4078260fa0e5c6466e6fc6d8b4d707f7169f0e7f35dda6ae1beec6c648

See more details on using hashes here.

Provenance

The following attestation bundles were made for ad_tech_inc_resilient_http-0.1.0.tar.gz:

Publisher: publish.yml on AD-Technology-Inc/resilient-http-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ad_tech_inc_resilient_http-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ad_tech_inc_resilient_http-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1ec73ff174946d332c4c7293314b366ca1e887f8d9fae40d8b2cc94102e26f86
MD5 8118832eac619db49944d4f71ad2e297
BLAKE2b-256 f6e23f3272c55240e8794270c9e4d5736118dbebe9a4b4a3944c2d51faaa802b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ad_tech_inc_resilient_http-0.1.0-py3-none-any.whl:

Publisher: publish.yml on AD-Technology-Inc/resilient-http-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page