Support disappearing messages
Disappearing messages are messages that are intended to be visible to users for only a short period of time. After the message expiration time passes, the messages are removed from the UI and deleted from local storage so the messages are no longer accessible to conversation participants.
App-level disappearing messages vs. network-level message expiration
Disappearing message behavior is enforced by apps, meaning that apps are responsible for removing messages from their UIs and local storage based on conditions set at the conversation level. As a feature, disappearing messages doesn't delete messages from the XMTP network.
Starting with XMTP Mainnet, the network will enforce message expiration to delete messages from the network after a retention period currently targeted at 6 months. This message expiration is a general condition of the network and is not related to the disappearing messages feature.
To learn more, see Message expiry in XIP-49: Decentralized backend for MLS messages.
Disappearing messages can be understood as app-level privacy that helps avoid leaving an easily accessible record in a messaging UI, while XMTP mainnet message expiration is the mechanism by which messages are deleted from the network.
Enable disappearing messages for a conversation
Conversation participants using apps that support disappearing messages will have a UX that honors the message expiration conditions. Conversation participants using apps that don't support disappearing messages won't experience disappearing message behavior.
Messages abide by the disappearing message settings for the conversation.
Permissions for setting disappearing message conditions
Who can set or change disappearing message settings depends on the conversation type:
- Group chats: Only group admins can set or change disappearing message settings
- DMs: Both participants can set or change disappearing message settings
Disappearing message settings
Disappearing message expiration conditions are expressed in nanoseconds (ns):
disappearStartingAtNs: Starting timestamp from which the message lifespan is calculated- In protocol messages, this appears as
message_disappear_from_ns
- In protocol messages, this appears as
retentionDurationInNs: Duration of time during which the message should remain visible to conversation participants- In protocol messages, this appears as
message_disappear_in_ns
- In protocol messages, this appears as
For example:
- Set
disappearStartingAtNsto the current time, such as1738620126404999936(nanoseconds since the Unix epoch of January 1, 1970). - Set
retentionDurationInNsto the message lifespan, such as 1800000000000000 (30 minutes). - Use
disappearStartingAtNsandretentionDurationInNsto calculate the message expiration time of1738620126404999936 + 1800000000000000 = 1740420126404999936.
To learn more, see conversation.rs.
Set disappearing message settings on conversation create
// DM
await client.conversations.newDm(inboxId, {
messageDisappearingSettings: {
fromNs: 1738620126404999936n,
inNs: 1800000000000000n,
},
});
// Group
await client.conversations.newGroup([inboxId], {
messageDisappearingSettings: {
fromNs: 1738620126404999936n,
inNs: 1800000000000000n,
},
});Update disappearing message settings for an existing conversation
When you update disappearing message settings, the system changes each field separately under the hood. This means you'll receive two separate protocol messages when settings are updated:
- One message for
message_disappear_from_ns(thedisappearStartingAtNsfield) - One message for
message_disappear_in_ns(theretentionDurationInNsfield)
// Update disappearing message settings
await conversation.updateMessageDisappearingSettings(
1738620126404999936n,
1800000000000000n
);
// Clear disappearing message settings
await conversation.removeMessageDisappearingSettings();Get the disappearing message settings for a conversation
// Get the disappearing message settings
const settings = await conversation.messageDisappearingSettings();
// Check if disappearing messages are enabled
const isEnabled = await conversation.isDisappearingMessagesEnabled();Automatic deletion from local storage
A background worker runs every one second to clean up expired disappearing messages. The worker automatically deletes expired messages from local storage. No additional action is required by integrators.
To learn more about the background worker, see disappearing_messages.rs.
Stream message deletions
Call streamMessageDeletions to return a stream of disappearing message IDs that have been deleted. Use this stream to be notified when messages have been deleted. This is a local stream that doesn't require network sync.
// Stream message deletions
const stream = await client.conversations.streamMessageDeletions();
// Listen for deleted message IDs
for await (const messageId of stream) {
console.log('Message deleted:', messageId);
// Update your UI to remove the message with this ID
}
// When done, end the stream
stream.end();Automatic removal from UI
Expired messages don't require manual removal from the UI. If your app UI updates when the local storage changes, expired messages will disappear automatically when the background worker deletes them from local storage.
Exclude from archive-based backups
You can exclude disappearing messages from archive-based backups.
To learn more, see Support archive-based backups.
Receive a disappearing message
On the receiving side, your app doesn't need to check expiration conditions manually. Receive and process messages as usual, and the background worker handles message expiration cleanup.
UX tips for disappearing messages
To ensure that users understand which messages are disappearing messages and their behavior, consider implementing:
- A distinct visual style: Style disappearing messages differently from regular messages (e.g., a different background color or icon) to indicate their temporary nature.
- A clear indication of the message's temporary nature: Use a visual cue, such as a timestamp or a countdown, to inform users that the message will disappear after a certain period.

