The content event stream only reaches subscribers on the instance that handled the write
- Dominant language
- C#
- Stars
- 6
- Forks
- 7
- Avg merge
- 4h 42m
- Merged PRs (30d)
- 307
Description
The content event stream fans out in process, on the instance that committed the write. `docs/delivery-api.md` states it plainly at "One instance, its own writes": a subscriber connected to instance A does not see a publish that went through instance B. `ContentChangeListener` repeats it in its own remarks.
This is a known limitation, written down, not a defect. Filing it because it is the thing that decides whether the event stream is a real feature or a single-instance one, and every deployment story we tell involves more than one instance.
## Why it matters more than it looks
A subscriber does not know it is missing anything. There is no gap, no error, no reconnect. The stream stays open and simply never mentions half the writes. A client cannot detect this, cannot work around it, and will conclude the data was not published.
Any deployment behind a load balancer with two or more API instances has this, which is the deployment `docs/deploy-in-production.md` and the k8s manifests describe.
## What to add
A shared bus so every instance broadcasts every committed change.
Postgres `LISTEN` / `NOTIFY` is the option with no new dependency: the database is already there, already the thing that committed the write, and the payload is small. Redis is the option that scales past what `NOTIFY` handles and is a new thing to run. Pick one and say why in the issue thread before writing code.
## What has to stay true
- Masking still goes through `PublicDelivery.ToPublic`. A field masked on the originating instance must not arrive unmasked on another.
- The tenant travels with the event, and a subscriber for tenant A never receives tenant B's change.
- The existing caps still hold: `Delivery:Events:MaxConnections` and `MaxConnectionsPerClient` are per instance, and a shared bus does not change that.
- Delivery to a subscriber is still best effort. A bus that guarantees ordering across instances is a bigger promise than the stream makes today, so do not make it by accident.
## Done when
- Two instances, one subscriber on each, a write through either: both see it.
- A test proves a tenant A subscriber does not receive a tenant B change delivered over the bus.
- `docs/delivery-api.md` loses the "One instance, its own writes" limitation, because it is no longer true.
Contributor guide
Research direction
Start with docs/delivery-api.md, docs/deploy-in-production.md, and the ContentChangeListener remarks to understand the current single-instance behavior. Decide between Postgres LISTEN/NOTIFY and Redis in the issue thread before changing code. Done means two instances share committed events, tenant isolation is tested, existing per-instance caps remain, and the documented limitation is removed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, postgresql
- Domain
- backend-api-design, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100