Retry without circuit breaker or load shedding

errorretry-without-adaptive-shedding

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.

Severity
error
Selects
every edge
Components in scope
2,366
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
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.

{{node.id}} style paths are filled in from the node, the edge or the design the finding is about.

Applies to · 2,366 components

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

This rule names no kind: it reads the design as a whole.
Tripped by · 30

Reference designs whose broken twin names this rule in its header. The gate reads the same header, and fails when a rule no design trips.

Source
# 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."

The same page as markdown, for an agent: /catalogue/rules/retry-without-adaptive-shedding.md