Retry Configuration#
FolioClient includes comprehensive retry logic powered by the tenacity library, along with granular timeout configuration for optimal HTTP client behavior. This modern retry system provides robust error handling with exponential backoff and extensive configuration options.
Overview#
The retry system automatically handles:
Server errors (502, 503, 504) and connection errors
Authorization errors (403) with automatic re-authentication
Remote protocol errors with HTTP client recreation
Exponential backoff to avoid overwhelming servers
Configurable limits to prevent infinite retry loops
Quick Start#
By default, no retries are performed - you must opt-in by setting environment variables:
# Enable basic server error retries
export FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES=3
# Enable auth error retries
export FOLIOCLIENT_MAX_AUTH_ERROR_RETRIES=2
# Your script will now automatically retry on transient errors
python your_folio_script.py
Environment Variables#
Server Error Retries#
Configure retry behavior for server errors (502, 503, 504) and connection issues:
Variable |
Default |
Description |
|---|---|---|
|
|
Maximum number of retry attempts (0 = no retries) |
|
|
Initial delay in seconds before first retry |
|
|
Exponential backoff multiplier |
|
|
Maximum wait time between retries |
Max Wait Configuration#
The FOLIOCLIENT_SERVER_ERROR_MAX_WAIT variable supports:
Number (e.g.,
"60"): Maximum wait time in seconds“unlimited”, “inf”, or “none”: No maximum (default)
Unset: Same as unlimited (maintains backward compatibility)
# Cap wait times at 2 minutes
export FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=120
# No cap on wait times (can grow very large)
export FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=unlimited
Auth Error Retries#
Configure retry behavior for authorization errors (403):
Variable |
Default |
Description |
|---|---|---|
|
|
Maximum number of retry attempts (0 = no retries) |
|
|
Initial delay in seconds before first retry |
|
|
Exponential backoff multiplier |
|
|
Maximum wait time between retries |
Note: Auth errors include automatic re-authentication before retry attempts.
Legacy Variables#
For backward compatibility, these legacy environment variables are also supported:
Legacy Variable |
Modern Equivalent |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Configuration Examples#
Conservative Configuration#
Suitable for most production environments:
# Moderate retries with reasonable limits
export FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES=3
export FOLIOCLIENT_SERVER_ERROR_RETRY_DELAY=5.0
export FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=60
export FOLIOCLIENT_MAX_AUTH_ERROR_RETRIES=2
export FOLIOCLIENT_AUTH_ERROR_RETRY_DELAY=5.0
export FOLIOCLIENT_AUTH_ERROR_MAX_WAIT=30
This creates retry timing like:
Attempt 1: Immediate
Attempt 2: 5s delay
Attempt 3: 15s delay
Attempt 4: 45s delay (capped at 60s for server errors)
Aggressive Configuration#
For environments with frequent transient issues:
# More retries with faster initial response
export FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES=5
export FOLIOCLIENT_SERVER_ERROR_RETRY_DELAY=2.0
export FOLIOCLIENT_SERVER_ERROR_RETRY_FACTOR=2.0
export FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=120
export FOLIOCLIENT_MAX_AUTH_ERROR_RETRIES=3
export FOLIOCLIENT_AUTH_ERROR_RETRY_DELAY=2.0
export FOLIOCLIENT_AUTH_ERROR_RETRY_FACTOR=2.0
Development Configuration#
Fast feedback for development environments:
# Quick retries for rapid development
export FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES=2
export FOLIOCLIENT_SERVER_ERROR_RETRY_DELAY=1.0
export FOLIOCLIENT_SERVER_ERROR_RETRY_FACTOR=2.0
export FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=10
export FOLIOCLIENT_MAX_AUTH_ERROR_RETRIES=1
export FOLIOCLIENT_AUTH_ERROR_RETRY_DELAY=1.0
Retry Timing Calculation#
The exponential backoff formula is:
delay = retry_delay * (retry_factor ^ attempt_number)
actual_delay = min(delay, max_wait)
Example Timing#
With default settings (FOLIOCLIENT_SERVER_ERROR_RETRY_DELAY=10, FOLIOCLIENT_SERVER_ERROR_RETRY_FACTOR=3, FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=unlimited):
Attempt |
Calculation |
Delay |
|---|---|---|
1 |
Immediate |
0s |
2 |
10 * 3^0 |
10s |
3 |
10 * 3^1 |
30s |
4 |
10 * 3^2 |
90s |
5 |
10 * 3^3 |
270s |
With FOLIOCLIENT_SERVER_ERROR_MAX_WAIT=60:
Attempt |
Calculation |
Capped Delay |
|---|---|---|
1 |
Immediate |
0s |
2 |
10 * 3^0 |
10s |
3 |
10 * 3^1 |
30s |
4 |
10 * 3^2 = 90s |
60s (capped) |
5 |
10 * 3^3 = 270s |
60s (capped) |
Advanced Usage#
Programmatic Configuration#
While environment variables are the primary configuration method, you can also configure retries programmatically:
import os
from folioclient import FolioClient
# Set configuration before creating client
os.environ['FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES'] = '3'
os.environ['FOLIOCLIENT_SERVER_ERROR_MAX_WAIT'] = '60'
client = FolioClient(...)
# All client methods now use the configured retry behavior
users = client.folio_get("/users", "users")
Monitoring Retries#
The retry system includes comprehensive logging. Enable INFO level logging to see retry attempts:
import logging
# Enable retry logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('folioclient.decorators')
# Now you'll see retry attempts in your logs
client = FolioClient(...)
users = client.folio_get("/users", "users")
Example log output:
INFO:folioclient.decorators:Retrying folio_get in 10.0 seconds...
INFO:folioclient.decorators:Retrying folio_get in 30.0 seconds...
Best Practices#
Production Environments#
Start conservative: Begin with 2-3 retries and moderate delays
Monitor and adjust: Use logging to understand retry patterns
Set reasonable limits: Always configure
FOLIOCLIENT_*_MAX_WAITto prevent very long delaysConsider downstream impact: More retries means more load on FOLIO servers
Development Environments#
Faster feedback: Use shorter delays and fewer retries
Enable logging: Monitor retry behavior during development
Test edge cases: Verify retry behavior under various failure conditions
Network-Specific Tuning#
Slow networks: Increase
FOLIOCLIENT_*_RETRY_DELAYandFOLIOCLIENT_*_MAX_WAITFast networks: Decrease
FOLIOCLIENT_*_RETRY_DELAYvalues for quicker recoveryUnreliable networks: Increase
FOLIOCLIENT_MAX_*_ERROR_RETRIESbut set reasonableFOLIOCLIENT_*_MAX_WAITStable networks: Minimal retries may be sufficient
Advanced Usage#
Custom Methods with Retry Protection#
If you’re subclassing FolioClient and adding custom methods, you can use the same retry decorators that protect the built-in methods. This is useful for complex operations that combine multiple FOLIO API calls, but you can’t use the built-in folio_* http methods (eg. you’re working with a PATCH api endpoint, or you just want greater control over the request).
Important Notes:
Decorators must be imported from
folioclient.decoratorsUse the same decorator order for consistent behavior
The
@use_client_sessiondecorator is required for HTTP operationsYour methods should follow the same patterns as built-in FolioClient methods
All retry configuration (environment variables) applies to your custom methods too
Handling Partial Success: When using retry decorators with multi-step operations, be aware that server errors can result in partial success (e.g., user created but response lost). For simpler cases, consider breaking complex operations into smaller, idempotent methods.
Decorator Functions:
@folio_retry_on_server_error: Retries on 502, 503, 504 errors and connection issues@folio_retry_on_auth_error: Retries on 403 errors with automatic re-authentication@handle_remote_protocol_error: Handles connection protocol errors@use_client_session: Required for HTTP operations that want to use the instance-levelhttpx.ClientorAsyncClientobjects, if available (the decorator will create a temporary client if one does not exist or is closed)@folio_errors: Translates httpx exceptions into FOLIO-specific exceptions
Attention
The handle_remote_protocol_error, use_client_session, and use_client_session_with_generator decorators can only be applied to methods of FolioClient or a subclass, as they assume that self is a FolioClient instance.
Troubleshooting#
Common Issues#
Issue: Retries not happening
Check: Verify environment variables are set
Check: Confirm error types match retry conditions (502, 503, 504 for server errors)
Issue: Retries taking too long
Solution: Set
FOLIOCLIENT_*_MAX_WAITto cap delaysSolution: Reduce
FOLIOCLIENT_*_RETRY_FACTORfor slower growth
Issue: Too many retries
Solution: Reduce
FOLIOCLIENT_MAX_*_ERROR_RETRIESSolution: Check for systemic issues causing repeated failures
Debugging#
Enable debug logging to see detailed retry information:
import logging
logging.getLogger('tenacity').setLevel(logging.DEBUG)
logging.getLogger('folioclient.decorators').setLevel(logging.DEBUG)
This will show:
Retry attempt details
Backoff calculations
Success/failure outcomes
Total retry duration
Migration from Custom Retry Logic#
If you were previously using custom retry logic, the new system provides:
Better performance: Tenacity is optimized and well-tested
More features: Jitter, advanced backoff strategies, comprehensive logging
Easier configuration: Environment variables instead of code changes
Consistency: Same retry behavior across all FolioClient methods
To migrate:
Remove custom retry code
Set appropriate environment variables
Test with your typical workloads
Adjust configuration as needed