Python resilience patterns including automatic retries

by wshobson · MIT license · ★ 39,857 on GitHub · updated Sep 21

Python Resilience Patterns cover

Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing timeouts, building fault-tolerant services, or handling transient failures.

---
name: python-resilience
description: Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing timeouts, building fault-tolerant services, or handling transient failures.
---

# Python Resilience Patterns

Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.

## When to Use This Skill

- Adding retry logic to external service calls
- Implementing timeouts for network operations
- Building fault-tolerant microservices
- Handling rate limiting and backpressure
- Creating infrastructure decorators
- Designing circuit breakers

Overview

Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.

Manual install (npx, ZIP)
Claude Codenpx skills add wshobson/agents --skill python-resilience -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \ | tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/python-development/skills/python-resilience
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/8e37e7a833b65a8b943b/python-resilience.zip" -OutFile "$env:TEMP\python-resilience.zip"; Expand-Archive "$env:TEMP\python-resilience.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md5.9 KB
  • references/1 file · 5.3 KB
Read the files here
wshobson/4236bb92 files
SKILL.md
Show the full text196 lines

Python Resilience Patterns

Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.

When to Use This Skill

  • Adding retry logic to external service calls
  • Implementing timeouts for network operations
  • Building fault-tolerant microservices
  • Handling rate limiting and backpressure
  • Creating infrastructure decorators
  • Designing circuit breakers

Core Concepts

1. Transient vs Permanent Failures

Retry transient errors (network timeouts, temporary service issues). Don't retry permanent errors (invalid credentials, bad requests).

2. Exponential Backoff

Increase wait time between retries to avoid overwhelming recovering services.

3. Jitter

Add randomness to backoff to prevent thundering herd when many clients retry simultaneously.

4. Bounded Retries

Cap both attempt count and total duration to prevent infinite retry loops.

Quick Start

from tenacity import retry, stop_after_attempt, wait_exponential_jitter

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def call_external_service(request: dict) -> dict:
    return httpx.post("https://api.example.com", json=request).json()

Fundamental Patterns

Pattern 1: Basic Retry with Tenacity

Use the tenacity library for production-grade retry logic. For simpler cases, consider built-in retry functionality or a lightweight custom implementation.

from tenacity import (
    retry,
    stop_after_attempt,
    stop_after_delay,
    wait_exponential_jitter,
    retry_if_exception_type,
)

TRANSIENT_ERRORS = (ConnectionError, TimeoutError, OSError)

@retry(
    retry=retry_if_exception_type(TRANSIENT_ERRORS),
    stop=stop_after_attempt(5) | stop_after_delay(60),
    wait=wait_exponential_jitter(initial=1, max=30),
)
def fetch_data(url: str) -> dict:
    """Fetch data with automatic retry on transient failures."""
    response = httpx.get(url, timeout=30)
    response.raise_for_status()
    return response.json()
Pattern 2: Retry Only Appropriate Errors

Whitelist specific transient exceptions. Never retry:

  • ValueError, TypeError - These are bugs, not transient issues
  • AuthenticationError - Invalid credentials won't become valid
  • HTTP 4xx errors (except 429) - Client errors are permanent
from tenacity import retry, retry_if_exception_type
import httpx

# Define what's retryable
RETRYABLE_EXCEPTIONS = (
    ConnectionError,
    TimeoutError,
    httpx.ConnectTimeout,
    httpx.ReadTimeout,
)

@retry(
    retry=retry_if_exception_type(RETRYABLE_EXCEPTIONS),
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def resilient_api_call(endpoint: str) -> dict:
    """Make API call with retry on network issues."""
    return httpx.get(endpoint, timeout=10).json()
Pattern 3: HTTP Status Code Retries

Retry specific HTTP status codes that indicate transient issues.

from tenacity import retry, retry_if_result, stop_after_attempt
import httpx

RETRY_STATUS_CODES = {429, 502, 503, 504}

def should_retry_response(response: httpx.Response) -> bool:
    """Check if response indicates a retryable error."""
    return response.status_code in RETRY_STATUS_CODES

@retry(
    retry=retry_if_result(should_retry_response),
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def http_request(method: str, url: str, **kwargs) -> httpx.Response:
    """Make HTTP request with retry on transient status codes."""
    return httpx.request(method, url, timeout=30, **kwargs)
Pattern 4: Combined Exception and Status Retry

Handle both network exceptions and HTTP status codes.

from tenacity import (
    retry,
    retry_if_exception_type,
    retry_if_result,
    stop_after_attempt,
    wait_exponential_jitter,
    before_sleep_log,
)
import logging
import httpx

logger = logging.getLogger(__name__)

TRANSIENT_EXCEPTIONS = (
    ConnectionError,
    TimeoutError,
    httpx.ConnectError,
    httpx.ReadTimeout,
)
RETRY_STATUS_CODES = {429, 500, 502, 503, 504}

def is_retryable_response(response: httpx.Response) -> bool:
    return response.status_code in RETRY_STATUS_CODES

@retry(
    retry=(
        retry_if_exception_type(TRANSIENT_EXCEPTIONS) |
        retry_if_result(is_retryable_response)
    ),
    stop=stop_after_attempt(5),
    wait=wait_exponential_jitter(initial=1, max=30),
    before_sleep=before_sleep_log(logger, logging.WARNING),
)
def robust_http_call(
    method: str,
    url: str,
    **kwargs,
) -> httpx.Response:
    """HTTP call with comprehensive retry handling."""
    return httpx.request(method, url, timeout=30, **kwargs)

Detailed worked examples and patterns

Detailed sections (starting with ## Advanced Patterns) live in references/details.md. Read that file when the navigation summary above is insufficient.

Best Practices Summary

  1. Retry only transient errors - Don't retry bugs or authentication failures
  2. Use exponential backoff - Give services time to recover
  3. Add jitter - Prevent thundering herd from synchronized retries
  4. Cap total duration - stop_after_attempt(5) | stop_after_delay(60)
  5. Log every retry - Silent retries hide systemic problems
  6. Use decorators - Keep retry logic separate from business logic
  7. Inject dependencies - Make infrastructure testable
  8. Set timeouts everywhere - Every network call needs a timeout
  9. Fail gracefully - Return cached/default values for non-critical paths
  10. Monitor retry rates - High retry rates indicate underlying issues
1---
2name: python-resilience
3description: Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing timeouts, building fault-tolerant services, or handling transient failures.
4---
5 
6# Python Resilience Patterns
7 
8Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.
9 
10## When to Use This Skill
11 
12- Adding retry logic to external service calls
13- Implementing timeouts for network operations
14- Building fault-tolerant microservices
15- Handling rate limiting and backpressure
16- Creating infrastructure decorators
17- Designing circuit breakers
18 
19## Core Concepts
20 
21### 1. Transient vs Permanent Failures
22 
23Retry transient errors (network timeouts, temporary service issues). Don't retry permanent errors (invalid credentials, bad requests).
24 
25### 2. Exponential Backoff
26 
27Increase wait time between retries to avoid overwhelming recovering services.
28 
29### 3. Jitter
30 
31Add randomness to backoff to prevent thundering herd when many clients retry simultaneously.
32 
33### 4. Bounded Retries
34 
35Cap both attempt count and total duration to prevent infinite retry loops.
36 
37## Quick Start
38 
39```python
40from tenacity import retry, stop_after_attempt, wait_exponential_jitter
41 
42@retry(
43 stop=stop_after_attempt(3),
44 wait=wait_exponential_jitter(initial=1, max=10),
45)
46def call_external_service(request: dict) -> dict:
47 return httpx.post("https://api.example.com", json=request).json()
48```
49 
50## Fundamental Patterns
51 
52### Pattern 1: Basic Retry with Tenacity
53 
54Use the `tenacity` library for production-grade retry logic. For simpler cases, consider built-in retry functionality or a lightweight custom implementation.
55 
56```python
57from tenacity import (
58 retry,
59 stop_after_attempt,
60 stop_after_delay,
61 wait_exponential_jitter,
62 retry_if_exception_type,
63)
64 
65TRANSIENT_ERRORS = (ConnectionError, TimeoutError, OSError)
66 
67@retry(
68 retry=retry_if_exception_type(TRANSIENT_ERRORS),
69 stop=stop_after_attempt(5) | stop_after_delay(60),
70 wait=wait_exponential_jitter(initial=1, max=30),
71)
72def fetch_data(url: str) -> dict:
73 """Fetch data with automatic retry on transient failures."""
74 response = httpx.get(url, timeout=30)
75 response.raise_for_status()
76 return response.json()
77```
78 
79### Pattern 2: Retry Only Appropriate Errors
80 
81Whitelist specific transient exceptions. Never retry:
82 
83- `ValueError`, `TypeError` - These are bugs, not transient issues
84- `AuthenticationError` - Invalid credentials won't become valid
85- HTTP 4xx errors (except 429) - Client errors are permanent
86 
87```python
88from tenacity import retry, retry_if_exception_type
89import httpx
90 
91# Define what's retryable
92RETRYABLE_EXCEPTIONS = (
93 ConnectionError,
94 TimeoutError,
95 httpx.ConnectTimeout,
96 httpx.ReadTimeout,
97)
98 
99@retry(
100 retry=retry_if_exception_type(RETRYABLE_EXCEPTIONS),
101 stop=stop_after_attempt(3),
102 wait=wait_exponential_jitter(initial=1, max=10),
103)
104def resilient_api_call(endpoint: str) -> dict:
105 """Make API call with retry on network issues."""
106 return httpx.get(endpoint, timeout=10).json()
107```
108 
109### Pattern 3: HTTP Status Code Retries
110 
111Retry specific HTTP status codes that indicate transient issues.
112 
113```python
114from tenacity import retry, retry_if_result, stop_after_attempt
115import httpx
116 
117RETRY_STATUS_CODES = {429, 502, 503, 504}
118 
119def should_retry_response(response: httpx.Response) -> bool:
120 """Check if response indicates a retryable error."""
121 return response.status_code in RETRY_STATUS_CODES
122 
123@retry(
124 retry=retry_if_result(should_retry_response),
125 stop=stop_after_attempt(3),
126 wait=wait_exponential_jitter(initial=1, max=10),
127)
128def http_request(method: str, url: str, **kwargs) -> httpx.Response:
129 """Make HTTP request with retry on transient status codes."""
130 return httpx.request(method, url, timeout=30, **kwargs)
131```
132 
133### Pattern 4: Combined Exception and Status Retry
134 
135Handle both network exceptions and HTTP status codes.
136 
137```python
138from tenacity import (
139 retry,
140 retry_if_exception_type,
141 retry_if_result,
142 stop_after_attempt,
143 wait_exponential_jitter,
144 before_sleep_log,
145)
146import logging
147import httpx
148 
149logger = logging.getLogger(__name__)
150 
151TRANSIENT_EXCEPTIONS = (
152 ConnectionError,
153 TimeoutError,
154 httpx.ConnectError,
155 httpx.ReadTimeout,
156)
157RETRY_STATUS_CODES = {429, 500, 502, 503, 504}
158 
159def is_retryable_response(response: httpx.Response) -> bool:
160 return response.status_code in RETRY_STATUS_CODES
161 
162@retry(
163 retry=(
164 retry_if_exception_type(TRANSIENT_EXCEPTIONS) |
165 retry_if_result(is_retryable_response)
166 ),
167 stop=stop_after_attempt(5),
168 wait=wait_exponential_jitter(initial=1, max=30),
169 before_sleep=before_sleep_log(logger, logging.WARNING),
170)
171def robust_http_call(
172 method: str,
173 url: str,
174 **kwargs,
175) -> httpx.Response:
176 """HTTP call with comprehensive retry handling."""
177 return httpx.request(method, url, timeout=30, **kwargs)
178```
179 
180## Detailed worked examples and patterns
181 
182Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.
183 
184## Best Practices Summary
185 
1861. **Retry only transient errors** - Don't retry bugs or authentication failures
1872. **Use exponential backoff** - Give services time to recover
1883. **Add jitter** - Prevent thundering herd from synchronized retries
1894. **Cap total duration** - `stop_after_attempt(5) | stop_after_delay(60)`
1905. **Log every retry** - Silent retries hide systemic problems
1916. **Use decorators** - Keep retry logic separate from business logic
1927. **Inject dependencies** - Make infrastructure testable
1938. **Set timeouts everywhere** - Every network call needs a timeout
1949. **Fail gracefully** - Return cached/default values for non-critical paths
19510. **Monitor retry rates** - High retry rates indicate underlying issues
196 
View all files on GitHub →

Details

Updated
Sep 21, 2026
License
MIT
Stars on the repo
★ 39,857
Checked
Source
wshobson/agents ↗
Creator
wshobson · 179 listings
View creator

Similar skills

See all →
SkillA task is too large for one model passAdvisor orchestrator workerShubhamsaboo/awesome-llm-apps · by ShubhamsabooUse when a task is too large for one model pass, needs parallel research or generation across many subtasks (like researching a dozen competitors at once), or the user asks to orchestrate multiple models, split work across a model team, run an advisor-worker loop, have a stronger model review the plan while cheap workers execute, or says "too big for one model" or "fan this out". Not for single-file edits or tasks one model handles in one pass.★ 139k GitHub starsSkillRun the CCS Align seat's hourly breathing cycleCCS Align — Worker Watch seat (Phases 0–2 shipped; Phase 3 = verify / sign-off)thedotmack/claude-mem · by thedotmackRun the CCS Align seat's hourly breathing cycle — prove the local claude-mem worker is healthy, pull needle observations through search → timeline → get_observations, land them in a seat-owned middle cache via atomic grab → append → filter exclude-marks → replace, manage exclude marks, and walk house → project → seat rules to detect conflicts (SHADOW_HOUSE, DENY_ALLOW, DRIFT, CLOCK_HEADER) with an append-only rules-report.md. Use when asked to run CCS Align, breathe the alignment seat, refresh the middle cache, exclude or restore an observation, walk rules, check rules conflicts, or check the Worker Watch board.★ 95.6k GitHub starsSkillSummarize and review what changed while you were awayCatchup — Async-Team Return Briefingoliver-kriska/claude-elixir-phoenix · by oliver-kriskaSummarize and review what changed while you were away. Use after a weekend, vacation, or flight to check missed PRs, git commits, Linear tickets, and meetings — one prioritized brief, not a firehose.★ 560 GitHub starsSkillMaster Python asyncio, concurrent programmingAsync python patternswshobson/agents · by wshobsonMaster Python asyncio, concurrent programming, and async/await patterns for high-performance applications. Use when building async APIs, concurrent systems, or I/O-bound applications requiring non-blocking operations.★ 39.9k GitHub starsSkillMaster Go concurrency with goroutines, channelsGo concurrency patternswshobson/agents · by wshobsonMaster Go concurrency with goroutines, channels, sync primitives, and context. Use when building concurrent Go applications, implementing worker pools, or debugging race conditions.★ 39.9k GitHub starsSkillDesign microservices architectures with service boundariesMicroservices patternswshobson/agents · by wshobsonDesign microservices architectures with service boundaries, event-driven communication, and resilience patterns. Use when building distributed systems, decomposing monoliths, or implementing microservices.★ 39.9k GitHub stars

More from wshobson

SkillMaster C/.NET backend development patterns for buildingwshobson/agents · by wshobsonMaster C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.★ 39.9k GitHub starsSkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliancewshobson/agents · by wshobsonImplement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.★ 39.9k GitHub starsSkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Designwshobson/agents · by wshobsonMaster Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.★ 39.9k GitHub starsSkillMigrate from AngularJS to Angular using hybrid modeAngular migrationwshobson/agents · by wshobsonMigrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.★ 39.9k GitHub starsSkillUnderstand anti-reversing, obfuscationAnti reversing techniqueswshobson/agents · by wshobsonUnderstand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.★ 39.9k GitHub starsSkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patternswshobson/agents · by wshobsonBuild production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.★ 39.9k GitHub stars