All Posts
Chaos TestingTestingAPIs

Chaos Testing: How to Break Your API on Purpose (And Why You Should)

Kiran MayeeMarch 28, 20269 min read

Chaos testing means injecting controlled failures into your system so you can verify resilience before production traffic discovers weak points. You do not need enterprise-scale infrastructure to do it well.

Most applications are tested on ideal paths: fast responses, valid payloads, healthy dependencies. Real production systems are not ideal. APIs time out. Upstreams return 503. Rate limits appear unexpectedly. Chaos testing turns those "rare" cases into normal test cases.

Why Chaos Testing Matters for API Teams

  • Prevents blank-screen failures in frontend apps.
  • Validates retry and backoff logic under stress.
  • Confirms circuit breakers and fallbacks actually work.
  • Builds confidence in incident response before incidents happen.

Start Small: HTTP Error Injection

You can begin with one endpoint and one error code. For example, inject 500 responses into 20% of requests and observe client behavior. Do users see a helpful message? Does your retry policy avoid request storms? Do logs contain enough context for debugging?

Core Scenarios to Simulate

  1. 500 Internal Server Error: validate fallback UI and server alerts.
  2. 503 Service Unavailable: verify retry with jitter and bounded attempts.
  3. 429 Too Many Requests: honor retry-after and slow down clients.
  4. Timeouts: ensure clients fail fast and recover gracefully.
  5. Partial payload corruption: protect parsers and validation boundaries.

Simple Resilient Client Pattern

async function fetchWithRetry(url, opts) {
  const maxAttempts = 3;
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
    try {
      const res = await fetch(url, opts);
      if (res.status === 429 || res.status === 503) {
        if (attempt === maxAttempts) throw new Error('Retry exhausted');
        await wait(200 * attempt);
        continue;
      }
      if (!res.ok) throw new Error('HTTP ' + res.status);
      return await res.json();
    } catch (err) {
      if (attempt === maxAttempts) throw err;
      await wait(150 * attempt);
    }
  }
}

function wait(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

Frontend Resilience Checklist

  • Loading state appears quickly and never hangs forever.
  • Error state includes retry and context.
  • Empty state is distinct from failed state.
  • Critical actions are idempotent and safe on retry.
  • User input is preserved when requests fail.

How to Run Chaos Tests with moqapi.dev

moqapi.dev lets you configure controlled failures at the mock layer. You can inject status codes, latency, and intermittent failures without changing production systems. That means fast iteration and low risk during development and QA.

Suggested Rollout Plan

  1. Week 1: one endpoint, 10% 500 injection.
  2. Week 2: add 429 and timeout scenarios.
  3. Week 3: include key user journeys end-to-end.
  4. Week 4: gate releases on resilience checks for critical flows.

Observability Requirements

Chaos tests are only useful when outcomes are measurable. Track:

  • Error rates by endpoint and status code.
  • Retry attempt distribution.
  • P95/P99 latency under fault injection.
  • User-visible failure rate for key journeys.

Common Chaos Testing Anti-Patterns

  • Injecting too much failure too early and learning nothing specific.
  • Running tests without clear hypotheses.
  • Treating chaos as a one-time event, not a recurring practice.
  • Skipping frontend verification and only testing backend metrics.

A Practical Example

Suppose checkout calls payment API. Inject 503 for 15% of payment requests. Success criteria might include: retry attempts capped at three, user sees actionable message, no duplicate charges, and support logs include correlation IDs. If any criterion fails, fix before launch.

From Chaos to Confidence

The goal is not to break systems for drama. The goal is to discover weak assumptions while fixes are cheap. Small, repeated chaos exercises produce resilient products and calmer on-call rotations.

Start Today

You can begin chaos testing with a single endpoint and one error mode in under an hour. Configure controlled API failures, validate client behavior, and expand scope gradually. Build your first fault-injection workflow at moqapi.dev/signup.

Backend Safeguards to Pair with Chaos Testing

Chaos is most effective when paired with protective controls in the service layer. Add circuit breakers for unstable upstream dependencies, request timeouts with sane defaults, and idempotency keys for write operations. These controls reduce blast radius while your tests intentionally create failure pressure.

  • Circuit breaker: short-circuit calls after repeated failures.
  • Timeout budget: fail fast instead of hanging threads.
  • Retry policy: exponential backoff with jitter.
  • Idempotency: prevent duplicate side effects during retries.

Runbook Template for a Chaos Exercise

  1. Define hypothesis: which failure should the system tolerate?
  2. Pick injection scope: endpoint, status code, and percentage.
  3. Define success metrics: UX, latency, retries, error budgets.
  4. Execute for a fixed time window.
  5. Record findings and assign remediation tasks.

Example Game Day Scenario

Scenario: profile page depends on user service and billing service. Inject 503 from billing at 25% for 20 minutes. Expected behavior: profile basics still render, billing widget shows retry CTA, and logs include correlation IDs. If the page crashes or spins indefinitely, resilience is insufficient.

How Often Should You Run Chaos Tests?

For critical user journeys, run at least weekly in pre-production and monthly in production-like environments with narrow blast radius. Also run targeted chaos checks before major launches, infrastructure migrations, and dependency upgrades.

Long-Term Outcome

Teams that treat chaos testing as a routine engineering habit reduce incident severity and recovery time. More importantly, they design systems that degrade gracefully, so users stay productive even when dependencies fail.

Share this article:

About the Author

Kiran Mayee

Founder and sole developer of moqapi.dev. Full-stack engineer with deep experience in API platforms, serverless runtimes, and developer tooling. Built moqapi to solve the mock data and deployment friction she experienced firsthand building production APIs.

Ready to build?

Start deploying serverless functions in under a minute.

Get Started Free