CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/API & SDK
API & SDK/2026-03-27Advanced

Claude API Production Resilience Patterns — Model Routing, Circuit Breakers, and Fallback Strategies for Indie Teams

Production resilience patterns for Claude API: circuit breakers, intelligent model routing, fallback chains, exponential backoff with jitter, and disaster recovery — with TypeScript implementations and operational lessons from running Dolice Labs across four sites as an indie developer.

api38production111resilience10circuit-breaker4retry7fallback8error-handling11typescript11

Premium Article

When you run the Claude API in production, failures are not a matter of if but when. Rate limits, response timeouts, temporary service disruptions — these are everyday realities for any LLM-powered application at scale. The difference between a frustrating user experience and a seamless one lies in how your system handles these failures.

I'm Masaki Hirokawa, an indie developer. I run Dolice Labs — Claude Lab, Gemini Lab, Antigravity Lab, and Rork Lab — four production sites on Cloudflare Workers, all of which call the Claude API on hot paths. The patterns in this guide were not learned from textbooks; they were earned from actually keeping these sites alive through real outages.

This guide walks you through five resilience patterns for Claude API applications: circuit breakers, intelligent model routing, fallback chains, retry strategies with exponential backoff, and disaster recovery. Every pattern includes production-ready TypeScript code you can drop into your project today, with operational notes from running the same patterns in production myself.

Why LLM Applications Need Specialized Resilience Engineering

LLM applications face unique failure modes that traditional web API resilience patterns don't fully address.

First, there's response time unpredictability. Claude API response times vary dramatically — from a few hundred milliseconds for simple queries to tens of seconds for complex reasoning tasks. Static timeouts simply don't work here.

Second, rate limit cascading is a real threat. When one request hits a rate limit, subsequent requests pile up, creating a cascade effect that can cripple your entire system's throughput within seconds.

Third, there's the cost explosion risk. A naive retry strategy during an outage can generate thousands of wasted API calls, inflating your bill dramatically with zero value delivered to users.

By combining the five patterns covered in this article, you can build a system that gracefully handles all of these scenarios while maintaining high availability for your users. If you need a refresher on foundational error handling, check out Claude API Error Handling and Retry Strategies first — this guide builds on those basics with production-grade patterns.

Implementing the Circuit Breaker Pattern

The circuit breaker is your first line of defense against cascading failures. Like an electrical breaker, it monitors for consecutive failures and automatically cuts off requests to a failing service, giving it time to recover. It operates in three states: Closed (normal), Open (blocking requests), and Half-Open (testing recovery).

// circuit-breaker.ts — Circuit breaker implementation for Claude API
interface CircuitBreakerConfig {
  failureThreshold: number;    // Failures before opening the circuit
  resetTimeout: number;        // Time before attempting recovery (ms)
  halfOpenMaxAttempts: number;  // Max attempts in half-open state
  monitorWindow: number;       // Failure counting window (ms)
}
 
type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
 
class ClaudeCircuitBreaker {
  private state: CircuitState = 'CLOSED';
  private failureCount = 0;
  private lastFailureTime = 0;
  private halfOpenAttempts = 0;
  private successCount = 0;
 
  constructor(
    private config: CircuitBreakerConfig = {
      failureThreshold: 5,
      resetTimeout: 30_000,
      halfOpenMaxAttempts: 3,
      monitorWindow: 60_000,
    }
  ) {}
 
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    // Open state: reject requests immediately
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailureTime >= this.config.resetTimeout) {
        this.transitionTo('HALF_OPEN');
      } else {
        throw new CircuitOpenError(
          `Circuit is OPEN. Retry after ${this.remainingResetTime()}ms`
        );
      }
    }
 
    // Half-open state: limit probe attempts
    if (this.state === 'HALF_OPEN' &&
        this.halfOpenAttempts >= this.config.halfOpenMaxAttempts) {
      this.transitionTo('OPEN');
      throw new CircuitOpenError('Half-open attempts exhausted');
    }
 
    try {
      if (this.state === 'HALF_OPEN') this.halfOpenAttempts++;
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }
 
  private onSuccess(): void {
    if (this.state === 'HALF_OPEN') {
      this.successCount++;
      // Two consecutive successes in half-open → transition to CLOSED
      if (this.successCount >= 2) {
        this.transitionTo('CLOSED');
      }
    }
    this.failureCount = 0;
  }
 
  private onFailure(): void {
    this.failureCount++;
    this.lastFailureTime = Date.now();
 
    if (this.state === 'HALF_OPEN') {
      // Any failure in half-open → back to OPEN
      this.transitionTo('OPEN');
    } else if (this.failureCount >= this.config.failureThreshold) {
      this.transitionTo('OPEN');
    }
  }
 
  private transitionTo(newState: CircuitState): void {
    console.log(`[CircuitBreaker] ${this.state} → ${newState}`);
    this.state = newState;
    if (newState === 'CLOSED') {
      this.failureCount = 0;
      this.successCount = 0;
    } else if (newState === 'HALF_OPEN') {
      this.halfOpenAttempts = 0;
      this.successCount = 0;
    }
  }
 
  private remainingResetTime(): number {
    return Math.max(
      0,
      this.config.resetTimeout - (Date.now() - this.lastFailureTime)
    );
  }
 
  getState(): CircuitState {
    return this.state;
  }
}
 
class CircuitOpenError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'CircuitOpenError';
  }
}
 
// Usage example
const breaker = new ClaudeCircuitBreaker({
  failureThreshold: 5,
  resetTimeout: 30_000,   // Retry after 30 seconds
  halfOpenMaxAttempts: 3,
  monitorWindow: 60_000,
});
 
const result = await breaker.execute(async () => {
  return await anthropic.messages.create({
    model: 'claude-sonnet-4-6',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello' }],
  });
});
// Expected: API response on success, CircuitOpenError during outages

The key detail here is the monitorWindow configuration. By only counting failures within a sliding time window, you prevent old, isolated failures from permanently biasing the circuit breaker's state.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Concrete circuit breaker thresholds (5 errors / 30s) and per-usecase tuning tables that beat the textbook defaults
Cloudflare Workers CPU-time constraints that force you to split ResilienceManager across a Cron Triggers Worker and Durable Objects
Real RTO/RPO economics from running Dolice Labs across four production sites, including a Supervisor LLM swap from Sonnet to Haiku that dropped costs from ~$5/month to ~$1.25/month
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API & SDK2026-05-23
Absorbing Claude API 529 Overloaded in Production — Resilience Patterns from a 50M-Download Indie Studio
529 Overloaded won't go away with a naive exponential backoff. Drawing on lessons from 50 million app downloads, this piece walks through queue-based absorption, model-aware fallback, and circuit-breaker design with working code.
API & SDK2026-04-23
High-Availability Patterns for the Claude API — Making Sonnet/Haiku/Opus Fallback Work in Production
A single-model Claude API integration will fall over the first time rate limits or a regional hiccup land at peak hours. This is the production pattern for a Sonnet → Opus → Haiku fallback chain, with circuit breakers, streaming coverage, and the pitfalls you only learn the hard way.
API & SDK2026-03-31
Building Self-Healing AI Agents with Claude API — Error Detection, Auto-Recovery, and Graceful Degradation Patterns for Production
Learn how to build production-grade AI agents that automatically detect failures and self-heal using Claude API. Covers retry strategies, fallback chains, Supervisor patterns, and observability pipelines.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →