---
id: "stateful-hash-ring-without-ring-manager"
type: "rule"
severity: "warning"
url: "https://localhost:3000/catalogue/rules/stateful-hash-ring-without-ring-manager"
---

# Stateful hash ring without ring manager

A service on a consistent hash ring is not connected to a coordination service that owns the ring.

| | |
|---|---|
| Severity | warning |
| Selects | every node of kind app-server |
| Components in scope | 99 |

## Why

A stateful service on a consistent hash ring needs something that owns the ring: detect a dead host, pick a replacement, tell everyone. Without a coordination service the ring is edited by hand during the outage.

## What it checks

It looks at every node of kind app-server, and fires when:

- all of these hold:
  - the node's `shardingStrategy` is "consistent-hash"
  - this does not hold:
    - the node has at least one connected edge joining a coordination-service

Message template:

```
Service '{{node.id}}' is on a consistent hash ring but is not connected to a coordination service that manages the ring.
```

## Applies to

- [Application server](https://localhost:3000/catalogue/kinds/app-server.md) `app-server`

99 catalogue components fall under it.

## Tripped by

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

- [datadog-husky](https://localhost:3000/d/zeema/datadog-husky)
- [discord-messages](https://localhost:3000/d/zeema/discord-messages)
- [etsy-search](https://localhost:3000/d/zeema/etsy-search)
- [facebook-messenger](https://localhost:3000/d/zeema/facebook-messenger)
- [grab-geo](https://localhost:3000/d/zeema/grab-geo)
- [slack-messaging](https://localhost:3000/d/zeema/slack-messaging)
- [tinder-geo](https://localhost:3000/d/zeema/tinder-geo)
- [twitch-live](https://localhost:3000/d/zeema/twitch-live)
- [uber-dispatch](https://localhost:3000/d/zeema/uber-dispatch)

## Source (`rule` YAML, verbatim)

```yaml
# yaml-language-server: $schema=../schema/rule.schema.json
# A stateful service on a consistent hash ring needs something to own the ring: detect a
# dead host, pick a replacement and tell everyone. Without a ring manager (a
# coordination service) the ring is edited by hand during the outage.
# Tests "this node has no edge to a coordination service" rather than "the design has no
# coordination service" so it can co-fire with reconnect-stampede-without-guard, which
# requires one to exist.
# Tripped by: designs/slack-messaging.broken.yaml
schemaVersion: "1"
type: "rule"
id: "stateful-hash-ring-without-ring-manager"
severity: "warning"
select:
  node:
    kind: "app-server"
when:
  all:
    - prop: "shardingStrategy"
      equals: "consistent-hash"
    - not:
        hasEdge:
          direction: "any"
          peerKind: "coordination-service"
message: "Service '{{node.id}}' is on a consistent hash ring but is not connected to a coordination service that manages the ring."
```

Human page: https://localhost:3000/catalogue/rules/stateful-hash-ring-without-ring-manager
