Skip to content

Adding External Integrations

You’re adding code that calls an external API, a third-party service, or a database. These integrations are where production incidents often start. A missing timeout, an unbounded retry loop, or no error handling can take down your service when the external dependency misbehaves.

This guide shows how to use Unfault to catch these patterns before they ship.

When code calls external services, a few patterns cause most of the problems:

Missing timeouts: The external service hangs. Your request hangs. Your thread pool fills up. Your service stops responding.

Unbounded retries: The external service returns errors. Your code retries forever. You amplify the problem and possibly get rate limited.

No circuit breaker: The external service is down. Every request tries to reach it, fails, and takes the slow timeout path. Your service becomes unusably slow.

Swallowed errors: Something fails. The error gets caught and ignored. Debugging becomes archaeology.

No correlation IDs: A request fails somewhere in the chain. You can’t trace what happened across services.

Unfault detects all of these.

After writing code that connects to an external service:

Terminal window
unfault review --uncommitted --dimension stability

The --dimension stability flag focuses on the patterns most relevant to external integrations.

Example output:

High: Missing HTTP timeout
src/integrations/billing.py:42
HTTP request without timeout can hang indefinitely
High: Missing circuit breaker
src/integrations/billing.py:38
External service call without circuit breaker
Prerequisites: request classification, metrics collection
Medium: No retry logic
src/integrations/billing.py:42
HTTP call may fail transiently without retry

Not every finding requires immediate action. Here’s how to think about them:

Almost always worth adding. This is a low-effort, high-impact fix:

# Before
response = requests.get(url)
# After
response = requests.get(url, timeout=30.0)

Worth adding for idempotent operations. Be careful with non-idempotent ones:

# Safe for GET requests
@retry(stop=stop_after_attempt(3), wait=wait_exponential())
def fetch_data():
return requests.get(url, timeout=30.0)
# Be careful with POST requests that aren't idempotent

These require more infrastructure. If Unfault reports prerequisites are missing (metrics, request classification), this is a note for future work, not something to implement in this PR.

If Unfault reports empty catch blocks or swallowed exceptions, add appropriate handling:

# Before
try:
response = client.fetch()
except Exception:
pass # Empty catch
# After
try:
response = client.fetch()
except RequestException as e:
logger.error("Failed to fetch from billing service", error=str(e))
raise BillingServiceError("Could not reach billing service") from e
  1. Write the integration code

    Get it working first.

  2. Review for stability patterns

    Terminal window
    unfault review --uncommitted --dimension stability
  3. Add timeouts

    These are almost always worth adding.

  4. Add error handling

    Make sure errors are logged and propagated appropriately.

  5. Consider retries

    For idempotent operations on flaky services.

  6. Note infrastructure gaps

    If Unfault suggests circuit breakers or rate limiting but prerequisites are missing, document this for future work.

  7. Review again

    Terminal window
    unfault review --uncommitted --dimension stability

    Confirm the high-severity findings are addressed.

When an AI assistant writes integration code, it often forgets these operational concerns. Add to your AGENTS.md:

When writing code that calls external services:
1. Always include timeouts on HTTP calls
2. Consider retry logic for idempotent operations
3. Log errors with enough context to debug later
4. After writing, run: unfault review --uncommitted --dimension stability
5. Address high-severity findings before committing

See Use with AI Agents for full setup instructions.

Before writing new integration code, see how similar integrations work in your codebase:

Terminal window
unfault ask "How do we call external APIs in this project?"
unfault ask "What's our retry strategy for HTTP calls?"

Or find files that already use HTTP clients:

Terminal window
unfault graph library requests
unfault graph library httpx

This helps you match existing conventions rather than inventing new patterns.

Pre-commit Review

Review all changes before committing. Read more

Fault Injection

Test how your code handles failures. Read more

Rules Catalog

Browse stability rules in detail. Read more