Tag-Defined Event Behavior
Tag-Defined Event Behavior
This spec expands which events are considered replaceable, addressable, or ephemeral beyond the event kind ranges defined in NIP-01.
In this spec, the d tag is treated as a deduplication tag. Its value determines whether the event is replaceable or addressable.
Similarly, a NIP-40 expiration tag whose value matches the event's created_at timestamp marks the event as ephemeral.
Deduplication-Defined Replaceable Events
Events with the first d tag set to an empty string are considered replaceable events. They are unique by the combination of their kind and pubkey values.
Example:
{
"kind": 999,
"pubkey": "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca",
"tags": [
["d", ""],
...otherTags
]
...otherEventFields
}Deduplication-Defined Addressable Events
Events with the first d tag set to any value other than the empty string are considered addressable events. They are unique by the combination of their kind, pubkey, and d tag values.
Example:
{
"kind": 999,
"pubkey": "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca",
"tags": [
["d", "example"],
...otherTags
]
...otherEventFields
}Expiration-Defined Ephemeral Events
Events with a NIP-40 expiration tag set to the same value as their own created_at field are considered ephemeral events. Relays SHOULD broadcast them to clients with matching subscriptions and are not expected to persist them in their databases.
When deciding whether such an event is already expired, relays SHOULD allow a small clock skew before checking the expiration tag value (e.g. by adding 60 seconds to the expiration timestamp). Relays SHOULD NOT broadcast these events after that clock-skew window has passed.
Example:
{
"tags": [
["expiration", "1600000000"],
...otherTags
],
"created_at": 1600000000,
...otherEventFields
}Motivation
Without this mechanism, "editing" a regular event means issuing a kind:5 Event Deletion Request that references the event to be deleted and creating a new event with edited content or tags to replace the deleted one. The problem is that kind:5 events are permanent tombstones that can bloat relay databases if used to mimic an edit feature. Relying on the d tag for edits solves this problem for all events with kinds outside the ranges defined for replaceable or addressable events.
Matching the expiration tag to the created_at timestamp is enough to mark an event as ephemeral.
The existing NIP-01 kind ranges SHOULD continue to be supported by relays for legacy reasons.