---
id: "pubsub-replay-required"
type: "rule"
severity: "error"
url: "https://localhost:3000/catalogue/rules/pubsub-replay-required"
---

# Pub/Sub topic where replay is required

| | |
|---|---|
| Severity | error |
| Selects | every node of kind pubsub-topic |
| Components in scope | 13 |

## Why

The design declares that consumers must be able to replay history. A fan-out topic that does not retain messages cannot deliver that.

## What it checks

It looks at every node of kind pubsub-topic, and fires when:

- all of these hold:
  - the design requirement `messaging.replay` is true
  - the node's `replay` is false

Message template:

```
Topic '{{node.id}}' cannot replay messages, but the design requires replay. Use a stream or a replayable queue.
```

## Applies to

- [Pub/Sub topic](https://localhost:3000/catalogue/kinds/pubsub-topic.md) `pubsub-topic`

13 catalogue components fall under it.

## Tripped by

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

- [facebook-tao](https://localhost:3000/d/zeema/facebook-tao)
- [linear-sync](https://localhost:3000/d/zeema/linear-sync)
- [order-processing](https://localhost:3000/d/zeema/order-processing)
- [pokemon-go](https://localhost:3000/d/zeema/pokemon-go)
- [spotify-playback](https://localhost:3000/d/zeema/spotify-playback)

## Source (`rule` YAML, verbatim)

```yaml
# yaml-language-server: $schema=../schema/rule.schema.json
# The design declares that consumers must be able to replay history, but a fan-out topic
# without replay cannot deliver that. Tripped by designs/order-processing.broken.yaml.
schemaVersion: "1"
type: "rule"
id: "pubsub-replay-required"
severity: "error"
select:
  node:
    kind: "pubsub-topic"
when:
  all:
    - requirement: "messaging.replay"
      equals: true
    - prop: "replay"
      equals: false
message: "Topic '{{node.id}}' cannot replay messages, but the design requires replay. Use a stream or a replayable queue."
```

Human page: https://localhost:3000/catalogue/rules/pubsub-replay-required
