---
id: "retry-without-adaptive-shedding"
type: "rule"
severity: "error"
url: "https://localhost:3000/catalogue/rules/retry-without-adaptive-shedding"
---

# Retry without circuit breaker or load shedding

An edge retries into a service with no circuit breaker on the caller and no rate limiter in front of the callee.

| | |
|---|---|
| Severity | error |
| Selects | every edge |
| Components in scope | 2,366 |

## Why

Retries into a service that can neither shed load nor have its circuit opened produce a metastable failure: the retries keep the dependency saturated long after the original fault is gone. Either break the circuit at the caller or put an adaptive limiter in front of the callee.

## What it checks

It looks at every edge, and fires when:

- all of these hold:
  - the edge's `retryPolicy` is one of "fixed", "exponential" or "exponential-jitter"
  - this does not hold:
    - the edge's `circuitBreaker` is true
  - the edge's target node:
    - this does not hold:
      - the node has at least one incoming edge from a rate-limiter

Message template:

```
Edge '{{edge.from}}' -> '{{edge.to}}' retries without a circuit breaker, and '{{edge.to}}' has no rate limiter in front of it. Retry storms will cascade.
```

## Applies to

This rule is about an edge, so it belongs to a pair of nodes rather than one component.

2,366 catalogue components fall under it.

## Tripped by

Reference designs whose broken twin names this rule in its header:

- [ad-click-aggregation](https://localhost:3000/d/zeema/ad-click-aggregation)
- [booking-search](https://localhost:3000/d/zeema/booking-search)
- [cloudflare-edge](https://localhost:3000/d/zeema/cloudflare-edge)
- [digital-wallet](https://localhost:3000/d/zeema/digital-wallet)
- [distributed-message-queue](https://localhost:3000/d/zeema/distributed-message-queue)
- [doordash-delivery](https://localhost:3000/d/zeema/doordash-delivery)
- [etsy-search](https://localhost:3000/d/zeema/etsy-search)
- [figma-multiplayer](https://localhost:3000/d/zeema/figma-multiplayer)
- [github-mysql](https://localhost:3000/d/zeema/github-mysql)
- [gojek-platform](https://localhost:3000/d/zeema/gojek-platform)
- [google-maps](https://localhost:3000/d/zeema/google-maps)
- [grab-geo](https://localhost:3000/d/zeema/grab-geo)
- [hotel-reservation](https://localhost:3000/d/zeema/hotel-reservation)
- [hotstar-streaming](https://localhost:3000/d/zeema/hotstar-streaming)
- [linkedin-kafka](https://localhost:3000/d/zeema/linkedin-kafka)
- [lyft-envoy](https://localhost:3000/d/zeema/lyft-envoy)
- [meta-threads](https://localhost:3000/d/zeema/meta-threads)
- [metrics-monitoring](https://localhost:3000/d/zeema/metrics-monitoring)
- [netflix-streaming](https://localhost:3000/d/zeema/netflix-streaming)
- [nubank-core](https://localhost:3000/d/zeema/nubank-core)
- [pokemon-go](https://localhost:3000/d/zeema/pokemon-go)
- [proximity-service](https://localhost:3000/d/zeema/proximity-service)
- [shopify-flash-sale](https://localhost:3000/d/zeema/shopify-flash-sale)
- [snapchat-platform](https://localhost:3000/d/zeema/snapchat-platform)
- [stock-exchange](https://localhost:3000/d/zeema/stock-exchange)
- [stripe-payments](https://localhost:3000/d/zeema/stripe-payments)
- [tinder-geo](https://localhost:3000/d/zeema/tinder-geo)
- [uber-dispatch](https://localhost:3000/d/zeema/uber-dispatch)
- [whatsapp-messaging](https://localhost:3000/d/zeema/whatsapp-messaging)
- [zoom-video](https://localhost:3000/d/zeema/zoom-video)

## Source (`rule` YAML, verbatim)

```yaml
# yaml-language-server: $schema=../schema/rule.schema.json
# Retries into a service that cannot shed load or open a circuit are the recipe for a
# metastable failure: the retries keep the dependency saturated after the original
# fault is gone. Either break the circuit on the caller or put an adaptive limiter in
# front of the callee.
# Tripped by: designs/doordash-delivery.broken.yaml
schemaVersion: "1"
type: "rule"
id: "retry-without-adaptive-shedding"
severity: "error"
select:
  edge: {}
when:
  all:
    - field: "retryPolicy"
      in: ["fixed", "exponential", "exponential-jitter"]
    - not:
        field: "circuitBreaker"
        equals: true
    - to:
        not:
          hasEdge:
            direction: "in"
            peerKind: "rate-limiter"
message: "Edge '{{edge.from}}' -> '{{edge.to}}' retries without a circuit breaker, and '{{edge.to}}' has no rate limiter in front of it. Retry storms will cascade."
```

Human page: https://localhost:3000/catalogue/rules/retry-without-adaptive-shedding
