list_id is a dotted namespace, so document.doc_a1b2.watchers names the watchers of one document. Subscribing a user creates that list, so there is nothing to set up first.
Prerequisites
- A for each user you subscribe
- A published to send
Name the list after the entity
Pick a naming convention before you write any code, because the name is the only thing tying a list to the thing it belongs to. Alist_id holds up to six dot-separated segments:
Keeping the entity type in the first segment is what makes useful later. Entity ids with dots in them will not work, since a dot starts a new segment.
Wire up watching
1
Subscribe a user when they start watching
One call, and it is idempotent. creates the list if it does not exist, so you never check first.Call this wherever your app already records a watch: an explicit Watch button, or implicitly when someone comments or is assigned.
2
Notify everyone watching
Address the list instead of a user. Courier fans out to every subscriber and applies each recipient’s own .One send reaches every watcher, however many there are. You do not fan out yourself.
3
Unsubscribe when they stop watching
removes one watcher and leaves the rest alone.When the entity itself is deleted, delete the whole list with rather than removing watchers one at a time.
Ask who is watching what
Both directions of the relationship are readable, which is what makes this usable as your app’s own watch state rather than a write-only copy of it.
Both are .
Reach every entity of a kind
Because the entity type leads thelist_id, one pattern can address many lists at once. Swap list_id for list_pattern, where * matches a single segment:
A recipient watching several matched entities is deduplicated, so nobody receives the same message twice from one send.
Per-watcher preferences
A subscription can carry its ownpreferences, which apply to that subscription alone. Someone can follow a noisy project on digest while staying on instant notifications everywhere else. See for the status model.
Verify
1
Subscribe two users
Subscribe two test users to
document.doc_a1b2.watchers.2
Read the list back
Call and confirm both appear, which also proves the list was created by the subscribe call.
3
Send and check the logs
Send to the list, then open . You should see one message per subscriber, each with its own status.
4
Unsubscribe one and send again
The second send reaches one recipient. The unsubscribed user gets nothing.
FAQ
Do I have to create the list before subscribing anyone?
Do I have to create the list before subscribing anyone?
Subscribing creates the list when it does not exist, so a Watch button is one call with no setup and no existence check.
What happens when a watcher has opted out?
What happens when a watcher has opted out?
Courier applies each recipient’s preferences during fan-out, so an opted-out watcher is filtered and the rest still receive the message. The send does not fail.
How many watchers can one list hold?
How many watchers can one list hold?
Lists are built for fan-out, so a busy document with thousands of watchers is one send. Read members back with cursor pagination rather than all at once.
Can I scope this to one tenant?
Can I scope this to one tenant?
Add a
MEMBER_OF filter on the recipient alongside context.tenant_id. Tenant context alone sets branding and preferences without restricting who receives the message. See .Should I use an audience instead?
Should I use an audience instead?
Use an audience when membership follows from profile data, such as every user on the Pro plan. Watching is an explicit act that no profile field implies, so a list is the right shape.