Skip to content

MSC4354: Sticky Events#4354

Open
kegsay wants to merge 51 commits into
mainfrom
kegan/persist-edu
Open

MSC4354: Sticky Events#4354
kegsay wants to merge 51 commits into
mainfrom
kegan/persist-edu

Conversation

@kegsay

@kegsay kegsay commented Sep 16, 2025

Copy link
Copy Markdown
Member

@kegsay kegsay changed the title Sticky Events MSC4354: Sticky Events Sep 16, 2025
It wasn't particulalry useful for clients, and doesn't help equivocation much.
Comment thread proposals/4354-sticky-events.md Outdated
@turt2live turt2live added proposal A matrix spec change proposal. Process state. A-Client Server Client-Server API kind:core MSC which is critical to the protocol's success needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. labels Sep 16, 2025
@github-project-automation github-project-automation Bot moved this to Tracking for review in Spec Core Team Workflow Sep 16, 2025
@turt2live turt2live added the matrix-2.0 Required for Matrix 2.0 (note: do not rename - used in reports/links) label Sep 16, 2025
Comment thread proposals/4354-sticky-events.md
Comment thread proposals/4354-sticky-events.md Outdated
Comment thread proposals/4354-sticky-events.md
Comment thread proposals/4354-sticky-events.md
Comment thread proposals/4354-sticky-events.md Outdated
@benkuly

benkuly commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Just a note: Trixnity does implement this MSC with (as usual) high test coverage here: https://gitlab.com/connect2x/trixnity/trixnity/-/merge_requests/687

This does not mean, that I like how the MSC is right now (see my review).

@Saiv46

Saiv46 commented Apr 16, 2026

Copy link
Copy Markdown

This proposal should supercede #4357

jperkin pushed a commit to TritonDataCenter/pkgsrc that referenced this pull request May 14, 2026
Tested on NetBSD 9 amd64 by reporting pyproject.toml buglets upstream!

# Synapse 1.148.0 (2026-02-24)

## Features

- Support sending and receiving [MSC4354 Sticky Event](matrix-org/matrix-spec-proposals#4354) metadata. ([\#19365](element-hq/synapse#19365))

## Deprecations and Removals

- Remove support for [MSC3244: Room version capabilities](matrix-org/matrix-spec-proposals#3244) as the MSC was rejected. ([\#19429](element-hq/synapse#19429))
Comment on lines +3 to +4
MatrixRTC currently relies on allowing any user (PL0) to send `org.matrix.msc3401.call`
and `org.matrix.msc3401.call.member` state events into the room

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a link to #3401 could help to provide some context here.

Suggested change
MatrixRTC currently relies on allowing any user (PL0) to send `org.matrix.msc3401.call`
and `org.matrix.msc3401.call.member` state events into the room
MatrixRTC currently relies on allowing any user (PL0) to send the `org.matrix.msc3401.call`
and `org.matrix.msc3401.call.member` state events from
[MSC3401](https://github.com/matrix-org/matrix-spec-proposals/pull/3401) into the room

Comment on lines +10 to +12
1. Any user can modify other user's call state. MSC3757 tries to fix this, but in order to ensure other
users are unable to modify each other’s state, it proposes using string packing for authorization which
feels wrong, given the structured nature of events.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just linkifying MSC3757.

Suggested change
1. Any user can modify other user's call state. MSC3757 tries to fix this, but in order to ensure other
users are unable to modify each other’s state, it proposes using string packing for authorization which
feels wrong, given the structured nature of events.
1. Any user can modify other user's call state. [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757)
tries to fix this, but in order to ensure other users are unable to modify each other’s state, it proposes
using string packing for authorization which feels wrong, given the structured nature of events.

Comment thread proposals/4354-sticky-events.md Outdated
Comment thread proposals/4354-sticky-events.md Outdated
Comment on lines +294 to +299
Sending these old events will potentially increase the number of forward extremities in the room for the receiving server. This may impact state resolution
performance if there are many forward extremities. Servers MAY send dummy events to remove forward extremities (Synapse has the
option to do this since 2019). Alternatively, servers MAY choose not to add old sticky events to their forward extremities, but
this A) reduces eventual delivery guarantees by reducing the frequency of transitive delivery of events, B) reduces the convergence
rate when implementing ephemeral maps (see "Addendum: Implementing an ephemeral map"), as that relies on servers referencing sticky
events from other servers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just linking to the docs of said Synapse option.

Suggested change
Sending these old events will potentially increase the number of forward extremities in the room for the receiving server. This may impact state resolution
performance if there are many forward extremities. Servers MAY send dummy events to remove forward extremities (Synapse has the
option to do this since 2019). Alternatively, servers MAY choose not to add old sticky events to their forward extremities, but
this A) reduces eventual delivery guarantees by reducing the frequency of transitive delivery of events, B) reduces the convergence
rate when implementing ephemeral maps (see "Addendum: Implementing an ephemeral map"), as that relies on servers referencing sticky
events from other servers.
Sending these old events will potentially increase the number of forward extremities in the room for the receiving server. This may impact state resolution
performance if there are many forward extremities. Servers MAY send dummy events to remove forward extremities (Synapse has the
[option] to do this since 2019). Alternatively, servers MAY choose not to add old sticky events to their forward extremities, but
this A) reduces eventual delivery guarantees by reducing the frequency of transitive delivery of events, B) reduces the convergence
rate when implementing ephemeral maps (see "Addendum: Implementing an ephemeral map"), as that relies on servers referencing sticky
events from other servers.
[option]: https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html?highlight=dummy#dummy_events_threshold

Comment on lines +329 to +331
The lack of historical room key sharing may make some encrypted sticky events undecryptable when new users join the room.
[MSC4268: Sharing room keys for past messages](https://github.com/matrix-org/matrix-spec-proposals/pull/4268) would
help with this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This MSC has since been merged. So maybe we can reformulate this slightly?

Suggested change
The lack of historical room key sharing may make some encrypted sticky events undecryptable when new users join the room.
[MSC4268: Sharing room keys for past messages](https://github.com/matrix-org/matrix-spec-proposals/pull/4268) would
help with this.
The prior lack of historical room key sharing that could make some encrypted sticky events undecryptable when new users join the room
has been alleviated with [MSC4268: Sharing room keys for past messages](https://github.com/matrix-org/matrix-spec-proposals/pull/4268).


Servers could broadcast different values for the same key to different servers, causing the map to not converge:
the Byzantine Broadcast problem. Matrix already has a data structure to agree on shared state: the room DAG.
As such, this led to the prototype to the current proposal. By putting the data into the DAG, other servers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is some duplication here?

Suggested change
As such, this led to the prototype to the current proposal. By putting the data into the DAG, other servers
As such, this led to the current proposal. By putting the data into the DAG, other servers

Comment on lines +448 to +449
`(room_id, sender, type, content.sticky_key)` to track the current values in the map. Nothing stops
users sending multiple events with the same `sticky_key`. To deterministically tie-break, clients which

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in the 4-uple both need to be identical to require tie-breaking?

Suggested change
`(room_id, sender, type, content.sticky_key)` to track the current values in the map. Nothing stops
users sending multiple events with the same `sticky_key`. To deterministically tie-break, clients which
`(room_id, sender, type, content.sticky_key)` to track the current values in the map. Nothing stops
users sending multiple events with the same event type and `sticky_key`. To deterministically tie-break, clients which

Comment on lines +477 to +478
send another sticky event with just `content.sticky_key` set, with all the other application-specific fields omitted. Redacting
sticky events are an alternative way to do this, although this loses the `content.sticky_key` property so clients will need to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be "is" rather than "are"?

Suggested change
send another sticky event with just `content.sticky_key` set, with all the other application-specific fields omitted. Redacting
sticky events are an alternative way to do this, although this loses the `content.sticky_key` property so clients will need to
send another sticky event with just `content.sticky_key` set, with all the other application-specific fields omitted. Redacting
sticky events is an alternative way to do this, although this loses the `content.sticky_key` property so clients will need to

as having [left the session](https://github.com/matrix-org/matrix-spec-proposals/blob/toger5/matrixRTC/proposals/4143-matrix-rtc.md#leaving-a-session).
This is conceptually the same as deleting a key from the map. However, as the server is unaware of the `sticky_key`, it
cannot perform the delete operation for clients, and will instead send the empty content event down `/sync`. This means if
N users leave a call, there will be N sticky events present in `/sync` for the sticky duration specified.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They will only occur once in /sync though given what the proposals says further up?

Sticky events follow the same 'stream-like' behaviour as the timeline. This means clients will receive a sticky
event S once, and subsequent requests with an advanced since token will not return the same sticky event S.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

@turt2live turt2live mentioned this pull request May 19, 2026
9 tasks
Comment thread proposals/4354-sticky-events.md Outdated
Comment thread proposals/4354-sticky-events.md Outdated
Comment on lines +336 to +339
## Addendum

This section explains how sticky events can be used to implement a short-lived, per-user, per-room key-value store.
This technique would be used by MatrixRTC to synchronise RTC members, and should land in the spec as a suggested algorithm to follow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should downgrade this from a RECOMMENDATION to an example. The concrete keying semantics seem highly use case specific to me. The 4-uple (room_id, sender, type, content.sticky_key) and the tie-breaking logic outlined below may work for Matrix RTC. Other applications might have quite different requirements though. Specifying the local aggregation of sticky events should be left to features / MSCs using sticky events.

CC @toger5 with whom I chatted about this at the Matrix Community Summit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that the quadrupel is similar to the triple of a state event and application agnostic. I know, that there are other opinions than mine, but I still think, that sticky events are technically "just" temporary member-controlled state events and then it make sense to have rules like this on how they are working and stored locally.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] I still think, that sticky events are technically "just" temporary member-controlled state events [...]

I think that is exactly the question actually. Do we design sticky events as events with a state-event-like delivery guarantee and let applications do with them whatever they want? Or do we design them as state-like events with delivery guarantee and map-like semantics?

It feels like MatrixRTC is going to be the only user of this feature for a while. So I'm leaning towards treating the map logic as a MatrixRTC specialty first from where we could easily generalize it to arbitrary event types later when we find other use cases.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just because no other use cases are known doesn’t mean there aren’t any. Ultimately, it will have to be implemented for MatrixRTC anyway. I can’t see any reason why we shouldn’t make it available here as a general feature. Otherwise, applications will start misusing MatrixRTC for this purpose because it wasn’t defined as a general feature. From an implementation (SDK) perspective it is much closer to sticky events than to MatrixRTC: https://gitlab.com/connect2x/trixnity/trixnity/-/merge_requests/687

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just because no other use cases are known doesn’t mean there aren’t any.

Yes, true. I just think we may want to be cautious with prescribing logic for use cases that we don't yet know about because we cannot validate that this logic will actually be suitable.

Ultimately, the only difference in what I'm proposing is an event type filter chucked in front of the local aggregation logic for sticky events so that it is only applied to the Matrix RTC events. It feels easier to extend or remove that filter in future when we find other usages than to go the other way around.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec makes many recommendations for extensibility (e.g. event type naming convention) and things like extensible events are a good example of "this is a convention/recommendation, please do it" where SDK developers know where they stand in terms of reading fields they support. I don't see the sticky event map recommendation as anything novel.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems novel to me because we're prescribing aggregation logic for speculative features, not just naming conventions. I'm personally not convinced that we'll gain much by trying to bake the 4-uple mapping algorithm into SDKs this way. The algorithm itself doesn't appear very complicated to me and if somebody really needs x-uples for their feature, that should be rather trivial to implement.

Anyway, I've made us spend a lot of words on a really small part of the proposal, sorry. 🙈

I'm not going to die on this hill. It just seems unnecessarily limiting to me.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused why you think it's limiting. You can use sticky events without content.sticky_key. You're not forced to use ephemeral maps if you're using sticky keys. All it's doing is standardising map-like semantics so future features know they have this primitive they can make use of, which SDKs will already have anyway if they support MatrixRTC. Without this, the map-like semantics can be hidden away behind MatrixRTC and we'd see more MSCs adding the equivalent functionality.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is a nuance of how we'll write it into the spec. It sounded to me like it'll be a SHOULD for clients to maintain the generic map for any event with content.sticky_key.

Just defining it as a primitive (without normative language) and then having MatrixRTC be the only part of the spec that has normative MUSTs to use that primitive seems totally fine to me.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to conclude on this. How about we clarify the language like this?

Suggested change
## Addendum
This section explains how sticky events can be used to implement a short-lived, per-user, per-room key-value store.
This technique would be used by MatrixRTC to synchronise RTC members, and should land in the spec as a suggested algorithm to follow.
## Addendum
This section explains how sticky events can be used to implement a short-lived, per-user, per-room key-value store.
This technique would be used by MatrixRTC to synchronise RTC members, and should land in the spec as a (non-normative)
primitive with a recommendation to use it for future features.

Comment on lines +343 to +344
MatrixRTC relies on a per-user, per-device map of RTC member events. To implement this, this MSC proposes
a standardised mechanism for determining keys on sticky events, the `content.sticky_key` property:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're currently debating whether and how to chain a user's MatrixRTC membership events using relations. The current idea is that when a user joins an RTC session, they post their membership event without a relation. On any subsequent update of the membership event, a relation to the join event is added.

With that design we may not actually need sticky_key and could instead use the event ID of the join event (the related to event).

CC @toger5

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relations don't work over federation reliably, what exactly is your proposed flow?

@toger5 toger5 Jun 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we send a sticky_key as part of the encrypted content and let the client update the events based on that.
As there is no permanent sticky event the same keys can be reused later with different context.
Considering this it might be the more appropriate concept to use relation chains for mutating sticky items instead of a key based system?

The client logic would then automatically be:

  • there is only a set of sticky events. (no keyed map)
  • some of those items in the set might mutate as the sdk already does with edits (m.replace) anyway.

The flow:

  • join a call: send a new m.rtc.member sticky event
  • update your event (voice->video intent or just to not loose stickyness): send a m.rtc.member that m.replaces the old current one.
    • clients that have not yet synced immediately get the relation to the original join (which can help/is a different solution for call duration computation)
    • clients that already know about the soon expiring sticky event will emit an edit event on the MatrixEvent obj abstraction. (mutate the existing sticky item in the set)
  • The expiration can then be done per event. The original event expires but the edit event remains -> sticky event is still part of the set in the edited state. Which is another way to implement the current sticky expiration logic. (which might be simpler)

I think over federation this is equally stable as the sticky_key approach.
I think it is in general almost equivalent to the sticky_key approach but

  • sticky key = event_id OR m.relates_to.event_id
  • the sticky key is not encrypted anymore but still the metadata is blurred as we dont know if a relation is a m.room.message edit of a sticky m.room.message event or a call update.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think over federation it should work the same way sticky_key does given that both are transmitted as part of the event JSON.

If we're already using relations to chain the events anyway, that would spare us introducing another random number sticky_key property. The case where it wouldn't work is when the first sticky event already carries another relation (such as m.rtc.notification relating to the sender's m.rtc.member event).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case where it wouldn't work is when the first sticky event already carries another relation (such as m.rtc.notification relating to the sender's m.rtc.member event).

If it would not be m.replace but a m.reference relation it should still work as described?
The m.rtc.notification and the m.rtc.member events would be a separate entries in the "sticky set".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for understanding: How would you expect to persist sticky events from an SDK (MatrixRTC agnostic) perspective then? As a flat list? And the MatrixRTC implementation should find out which event "wins"?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of the other rules would change. I'm merely suggesting to swap sticky_key with m.relates_to["event_id"] in the algorithm. The same value would still require tie breaking using the rules from the proposal:

  • pick the one with the highest origin_server_ts + sticky.duration_ms (last to expire wins),
  • tie break on the one with the highest lexicographical event ID (A < Z).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't leak more than before

This isn't true though? One exposes "this is one sticky event among many" and the other is "this specifically relates to this event right here".

MatrixRTC also currently chains its membership events using relations.

Please be specific. What are "membership events"? m.room.member? RTC members? It's confusing because this thread uses terminology like "use the event ID of the join event".

What is the compound key for RTC members in general? One RTC session per... device? Not specified? Can you actually have multiple sessions on a single device?

chaining the events together with relations also has the benefit that you can query them using the /relations API which could make some operations faster.

Yes, but it baffles me why you'd do this without a use case for historical relations for the same RTC member?


From my position, it sounds very much like "hey, we're using the "membership event" ID as the sticky_key, let's just use relations?" without really thinking through if it makes sense to do. Like, the obvious advantage to this approach is that a gappy sync will return the latest event which is also a sharp edge case: the replace semantics there don't match the replace semantics of sticky events (origin_server_ts + sticky.duration_ms (last to expire wins)), so in some (all?) cases you'd be forced to walk back earlier edits to ensure you are in fact tracking the last to expire event.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't leak more than before

This isn't true though? One exposes "this is one sticky event among many" and the other is "this specifically relates to this event right here".

True, yes. I missed that. This isn't ideal but evidently we already accepted this shortcoming for the other usages of relations in the spec such as threads.

MatrixRTC also currently chains its membership events using relations.

Please be specific. What are "membership events"? m.room.member? RTC members? It's confusing because this thread uses terminology like "use the event ID of the join event".

Apologies for being sloppy with words. What #4143 currently proposes is:

m.rtc.member (initial event / join RTC session)
^                 ^
| m.reference     | m.reference
|                 |
m.rtc.member      |
(update due to    |
transport change  |
etc.)             |
                  |
                  |
                  |
                  m.rtc.member
                  (disconnect
                  from session)

As per #4143 this is using m.reference but we have been debating switching to m.replace. Conceptually this is the same though. Hopefully that makes it clear.

What is the compound key for RTC members in general? One RTC session per... device? Not specified? Can you actually have multiple sessions on a single device?

#4143 uses the mapping algorithm as specified in the addendum of this proposal. So the compound key is (room_id, sender, type, content.sticky_key). content.sticky_key is a UUID that is determined when sending the initial m.rtc.member member event to join a session. That means you can have multiple session on a single device.

chaining the events together with relations also has the benefit that you can query them using the /relations API which could make some operations faster.

Yes, but it baffles me why you'd do this without a use case for historical relations for the same RTC member?

The use case in MatrixRTC that we were discussing is reconstructing historical sessions, e.g. for a call history archive.

From my position, it sounds very much like "hey, we're using the "membership event" ID as the sticky_key, let's just use relations?" without really thinking through if it makes sense to do. Like, the obvious advantage to this approach is that a gappy sync will return the latest event which is also a sharp edge case: the replace semantics there don't match the replace semantics of sticky events (origin_server_ts + sticky.duration_ms (last to expire wins)), so in some (all?) cases you'd be forced to walk back earlier edits to ensure you are in fact tracking the last to expire event.

Well I opened this thread with the intention of us collectively thinking through if using relations to eliminate sticky_key is a sensible thing to do. So thank you for your feedback.

@toger5 and I will sync up on this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that with relations the server has visibility on both the event being sticky and the sticky key (from the relation), what if the server would reject sending sticky events when the sticky duration would make the event expire before the related-to event?

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jul 7, 2026
Tested on NetBSD 10 amd64 with 2026Q2 environment.

# Synapse 1.156.0 (2026-07-07)

## Features

- Expose [MSC4354 Sticky Events](matrix-org/matrix-spec-proposals#4354) over [MSC4186 (Simplified) Sliding Sync](matrix-org/matrix-spec-proposals#4186). ([\#19591](element-hq/synapse#19591))
- Stabilize support for sending ephemeral events to application services, as per [MSC2409](matrix-org/matrix-spec-proposals#2409). Contributed by @jason-famedly @ Famedly. ([\#19758](element-hq/synapse#19758))
- Include `allowed_room_ids` in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15.
  Contributed by @FrenchGithubUser @famedly. ([\#19762](element-hq/synapse#19762))
- [MSC4140: Cancellable delayed events](matrix-org/matrix-spec-proposals#4140): Allow authentication on delayed event management endpoints (such as `/restart`) to bypass ratelimits for unauthenticated requests based on the client IP address. ([\#19794](element-hq/synapse#19794))
- Add new metric `synapse_non_deactivated_user_count` which tracks the number of non-deactivated users in the database, split by `app_service`. ([\#19848](element-hq/synapse#19848))
- The `GET /_matrix/client/unstable/org.matrix.msc1763/retention/configuration` endpoint is now provided when retention
  is enabled and `experimental_features.msc1763_enabled` is enabled, based on
  [MSC1763](matrix-org/matrix-spec-proposals#1763). ([\#19853](element-hq/synapse#19853))
- Add experimental support for [MSC4491: Invite reasons in room creation](matrix-org/matrix-spec-proposals#4491). ([\#19874](element-hq/synapse#19874))


# Synapse 1.155.0 (2026-06-16)


# Synapse 1.154.0 (2026-06-04)

## Features

- Add support for [MSC4452: Preview URL capabilities API](matrix-org/matrix-spec-proposals#4452) which exposes a `io.element.msc4452.preview_url` capability.
  If `experimental_features.msc4452_enabled` is `true`, the `/_matrix/(client/v1/media|media/v3)/preview_url` endpoint
  now responds with a 403 status code when the capability is disabled. ([\#19715](element-hq/synapse#19715))


# Synapse 1.153.0 (2026-05-19)

## Features

- Make ACLs apply to EDUs per [MSC4163](matrix-org/matrix-spec-proposals#4163). ([\#18475](element-hq/synapse#18475))
- Stabilize [MSC3266: Room summary API](matrix-org/matrix-spec-proposals#3266), removing the experimental config flag `msc3266_enabled`. Contributed by @dasha-uwu. ([\#19720](element-hq/synapse#19720))
- Partial [MSC4311](matrix-org/matrix-spec-proposals#4311) implementation: `m.room.create` is now a required part of stripped `invite_state`/`knock_state` . Contributed by @FrenchGithubUser @famedly. ([\#19722](element-hq/synapse#19722))
- Expose `tombstoned` and `replacement_room` in room details on admin API endpoint `GET /_synapse/admin/v1/rooms/<room_id>`. Contributed by Noah Markert. ([\#19737](element-hq/synapse#19737))


# Synapse 1.152.1 (2026-05-07)


# Synapse 1.152.0 (2026-04-28)

## Features

- Add a ["Listing quarantined media changes" Admin API](https://element-hq.github.io/synapse/latest/admin_api/media_admin_api.html#listing-quarantined-media-changes) for retrieving a paginated record of when media became (un)quarantined. ([\#19558](element-hq/synapse#19558), [\#19677](element-hq/synapse#19677), [\#19694](element-hq/synapse#19694))
- Advertise [MSC4445](matrix-org/matrix-spec-proposals#4445) sync timeline order in `unstable_features`. ([\#19642](element-hq/synapse#19642))
- Report the Rust compiler version used in the Prometheus metrics. Contributed by Noah Markert. ([\#19643](element-hq/synapse#19643))
- Passthrough 'article' and 'profile' OpenGraph metadata on URL preview requests. ([\#19659](element-hq/synapse#19659))
- Add a way to re-sign local events with a new signing key. ([\#19668](element-hq/synapse#19668))
- Support [MSC4450: Identity Provider selection for User-Interactive Authentication with Legacy Single Sign-On](matrix-org/matrix-spec-proposals#4450). ([\#19693](element-hq/synapse#19693))
- Add experimental support for [MSC4242](matrix-org/matrix-spec-proposals#4242): State DAGs. Excludes federation support. ([\#19424](element-hq/synapse#19424))
- Adds [Admin API](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html) endpoints to
  list, fetch and delete user reports. ([\#19657](element-hq/synapse#19657))
- Reduce database disk space usage by pruning old rows from `device_lists_changes_in_room`. ([\#19473](element-hq/synapse#19473), [\#19709](element-hq/synapse#19709))


# Synapse 1.151.0 (2026-04-07)

## Features

- Add stable support for [MSC4284](matrix-org/matrix-spec-proposals#4284) Policy Servers. ([\#19503](element-hq/synapse#19503))
- Update and stabilize support for [MSC2666](matrix-org/matrix-spec-proposals#2666): Get rooms in common with another user. Contributed by @tulir @ Beeper. ([\#19511](element-hq/synapse#19511))
- Updated experimental support for [MSC4388: Secure out-of-band channel for sign in with QR](matrix-org/matrix-spec-proposals#4388). ([\#19573](element-hq/synapse#19573))
- Stabilize `room_version` and `encryption` fields in the space/room `/hierarchy` API (part of [MSC3266](matrix-org/matrix-spec-proposals#3266)). ([\#19576](element-hq/synapse#19576))
- Introduce a [configuration option](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#matrix_authentication_service) to allow using HTTP/2 over plaintext when Synapse connects to Matrix Authentication Service. ([\#19586](element-hq/synapse#19586))

## Deprecations and Removals

- Remove support for [MSC3852: Expose user agent information on Device](matrix-org/matrix-spec-proposals#3852) as the MSC was closed. ([\#19430](element-hq/synapse#19430))


# Synapse 1.150.0 (2026-03-24)

## Features

- Add experimental support for the [MSC4370](matrix-org/matrix-spec-proposals#4370) Federation API `GET /extremities` endpoint. ([\#19314](element-hq/synapse#19314))
- [MSC4140: Cancellable delayed events](matrix-org/matrix-spec-proposals#4140): When persisting a delayed event to the timeline, include its `delay_id` in the event's `unsigned` section in `/sync` responses to the event sender. ([\#19479](element-hq/synapse#19479))
- Expose [MSC4354 Sticky Events](matrix-org/matrix-spec-proposals#4354) over the legacy (v3) /sync API. ([\#19487](element-hq/synapse#19487))
- When Matrix Authentication Service (MAS) integration is enabled, allow MAS to set the user locked status in Synapse. ([\#19554](element-hq/synapse#19554))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Client Server Client-Server API A-VOIP kind:core MSC which is critical to the protocol's success matrix-2.0 Required for Matrix 2.0 (note: do not rename - used in reports/links) proposal A matrix spec change proposal. Process state. unresolved-concerns This proposal has at least one outstanding concern. Process state.

Projects

Status: Tracking for review

Development

Successfully merging this pull request may close these issues.