Architecture / 12 min read / 9 views

Designing resilient API boundaries

A practical guide to contracts, retries, backoff, and keeping service interfaces pleasant under pressure.

Start with the contract, not the transport

A resilient boundary begins as a shared language. Define the nouns, the errors, the retry shape, and the freshness guarantees before arguing about framework details.

The useful question is not only whether a service responds. It is whether the caller can make a sensible next decision when the service is slow, stale, partial, or unavailable.

Server racks with cool blue lighting in a data center

Boundaries become easier to reason about when contracts, observability, and ownership are visible together.

Make failure states explicit

Timeouts, partial data, duplicate requests, and downstream degradation should be named in the interface so callers can respond intentionally.

A good API makes the common path easy and the rough path legible. That is the difference between a boundary and a trapdoor.

resilient-fetch.ts

type RetryPolicy = {
  attempts: number;
  timeoutMs: number;
  retryOn: number[];
};

export async function fetchWithPolicy(url: string, policy: RetryPolicy) {
  for (let attempt = 1; attempt <= policy.attempts; attempt += 1) {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), policy.timeoutMs);

    try {
      const response = await fetch(url, { signal: controller.signal });
      if (!policy.retryOn.includes(response.status)) return response;
    } finally {
      clearTimeout(timeout);
    }
  }

  throw new Error("Request failed after retry policy was exhausted");
}

Keep recommendations close to the work

Related reading should extend the current idea: adjacent architecture notes, debugging guides, and examples from production incidents.

The best technical writing gives a reader one useful next action, then enough context to know when that action stops being wise.

Recent posts

Fresh notes from the archive, ordered by latest publication.

Designing resilient API boundaries | Biting the Bits | Biting the Bits