---
# System prepended metadata

title: 'Self-destructing messages: Implementation notes and estimations'

---

# Self-destructing messages: Implementation notes and estimations

## Sending synthetic redactions

* Store synthetic redactions in a table with the columns:
    * room ID (for conveniency)
    * event ID (the event we're redacting)
    * user ID (the user we're redacting for - the one whose sync stream the redaction will come down)
    * stream ID (at which stream ID to send the redaction)
    * event JSON
* On /sync and /messages:
    * Check if there's a synthetic redaction that fits within the range of stream IDs the sync request targets
    * If so, insert the synthetic redaction into the sync response, and prune the event
    * The synthetic redaction must include some details about why the message was redacted (need to amend the MSC)
    * We can't really delete rows from this table because we still need to consistently show the synthetic redactions after the message has been deleted

### Estimations

13 story points

## Time-based destruction (Time Limited Messages)

* Start a timer when an event is sent
* Send a synthetic redaction when the timer expires, to all local users in the room
    * (as a second step we could maybe limit it to members at the time the event was sent if the history visibility of the room is `joined`)
    * Also mark the event ready for deletion
    * If the history visibility is not `joined`, new users don't get extra time to read the event
* Editing messages does not change the destructibility of the message.  The server should ignore any m.self_destruct* entries in the content of an edit.
* Server behaviour handling an edited message should match its behaviour after a message was redacted.

### Estimations

13 story points

## Read receipt-based destruction (Burn After Read)

* On receiving a new RR: figure out if the event has been seen, by comparing its stream ordering with that of the event the RR is for
* Then same thing as time-based destruction
* Mark the event ready for deletion when all members (at the time the event was sent) that are still in the room have seen it
    * Check whether the event is ready for deletion both on receiving new RRs and when processing leave events
* Users joining the room later on only see the redacted message
* Editing messages does not change the destructibility of the message.  The server should ignore any `m.self_destruct*` entries in the content of an edit.
* Server behaviour handling an edited message should match its behaviour after a message was redacted.

### Estimations

8 story points

## Event deletion

* We want to take the grace period for redactions into account
* We don't want to send the event down sync once it's already been seen
* Create a table that stores the event ID and when it became ready for deletion (NULL for not ready yet)
* When the redaction grace period has passed, prune the event (see `CensorEventsStore._censor_redactions`)

### Estimations

5 story points

## Room setting

* Need to amend the MSC to support a state event an admin can use to turn on either mode
* Time-limited messages controlled by a room setting overlap quite a lot with message retenton policies (but doesn't work the same way and doesn't solve the same issues)
* State event that includes the `m.self_destruct*` keys
* All events sent while the state of the room are considered as having these keys
* Keys in events contents are ignored if the state event specifies a policy
* The homeserver should include the self-destructing information in the event body.

### Estimations

5 story points

## Client

Client side work:
- Room toggle ('enable for everyone')
- Disappearing messages settings
- Composer UI (clock symbol)
- Timeline UI
    - Time ('this message will be deleted')
    - Reason ('this message was set to disappear')
- Local message redaction timer 
    - _May not be needed depending on David's question below_

### iOS

13 story points

### Android

? (previously 13) story points

## Web

33 story points (2 sprints)

## Q&A

### David: Is it OK if when a client should delete an event and the app is in the BG, the app only deletes on wake?

Jake: That's fine. The message should just not flicker the message content
Alun: When you're going between apps you'll see the old message.
David: That's probably fine?
Jonny: The MSC currently [states](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/msc2228/proposals/2228-self-destructing-events.md#client-side-behaviour):
>Clients should locally remove events ... The synthetic redaction event sent by the local server then acts as a fallback for clients

So this would need to be changed if we wanted to rely solely on the redaction events (and not implement local timers).

### Alun: What will the timestamp in the message be?

For Time Limited Messages (`m.self_destruct_after`), it will be the unix timestamp at which point after the message should be deleted.

### Alun: In the UI, is there a clash if the users mix the two types

Jake: Both fields should be included

### AndrewM: Who wins if the room has a timer and the message has a timer

Whichever is shorter/earlier.

### Alun: If you have two clients and you are using Burn-After-Reading, when does the event get redacted on both of them?

Whichever clients' timer fires first. Other devices will need to look out for a read receipt coming from your other devices.

THIS IS AN IMPORTANT TEST CASE - reading on another device

### Arnaud: Are we targeting ElementX only?

Yes, ElementX only.

### David: Who made the Web estimate?

Arnaud: AndyBalaam I think - also worth poking his brain on what he thinks about implementing this on a client.