diff --git a/proposals/4495-selective-presence.md b/proposals/4495-selective-presence.md
new file mode 100644
index 00000000000..2477057b27f
--- /dev/null
+++ b/proposals/4495-selective-presence.md
@@ -0,0 +1,436 @@
+# MSC4495: Selective Presence
+
+Presence is widely known to be one of the most expensive features in the Matrix specification. Even with continued
+efforts to improve server implementations[^1][^2], large public deployments still disable outbound federated
+presence, citing its substantial performance impact. Presence, as it stands, is fundamentally flawed: users receive
+presence EDUs for every user they share a room with, even if the users have never interacted or have no interest in
+each other's presence; server operators often have no choice but to disable presence altogether to limit the
+excessive federation load; and users who do _not_ want to share potentially trackable information with public,
+federated rooms \- a limitation [acknowledged by the current specification][presence-v1-privacy] \- the only option
+they typically have is to, again, disable presence outright.
+
+This proposal introduces "Selective Presence," a system for users to decide precisely _who_ their
+presence is shared with. The benefits of this are twofold:
+1. the overall load on homeservers implementing presence is reduced substantially, as users only share their
+ presence with interested parties, and
+2. users benefit from improved privacy by only sharing such sensitive information with those they want to have
+ access to it.
+
+## Prior Art
+
+Prior to [MSC1819], a mechanism known as "presence lists" allowed users to subscribe to others' presence. In
+theory, it also offered a mechanism for other users to request your presence. However, Synapse historically
+[accepted all presence requests automatically][#4417], ultimately resulting in the feature's removal prior to r0.
+
+[MSC4325: Presence privacy][MSC4325] attempts to solve this problem by reintroducing a concept similar to Selective
+Presence. However, MSC4325 lacks some features integral to this proposal's goal of keeping UX similar to the
+current approach; room hints, for example, allow rooms to recommend that clients prompt users about whether they
+would like to share their presence, or forbid sharing presence altogether. This keeps presence usable for small
+communities, private rooms, and DMs, while reducing the load from federating presence in large public rooms.
+
+## Proposal
+
+### User Presence Sharing Preferences
+
+A new [`account_data`] entry, `m.presence.sharing`, is stored for modification by clients and use by homeservers.
+
+This event contains four properties:
+* The boolean `share_locally` enables sharing presence with all users with mutual rooms on the local homeserver
+ (default `false`)
+* Three **presence sharing map** objects, mapping one of several entity types to presence sharing behaviour:
+ 1. `users` mapping [User IDs][mxid-format] (default `{}`)
+ 2. `rooms` mapping [Room IDs][roomid-format] (default `{}`)
+ 3. `servers` mapping [Server Names][servername-format] (default `{}`)
+
+If the homeserver requires different defaults, for example setting `share_locally` to true in an organisation
+environment, the server MAY create a pre-populated `m.presence.sharing` event for a user when the user is created
+or if the user exists already but does not have an `m.presence.sharing` event. Otherwise, a missing property MUST
+be assumed to use its above default.
+
+No glob resolution is supported for any key in a presence sharing map.
+
+The string values of these presence sharing maps may be any of the following:
+* `"deny"`: Explicitly forbid sending presence to the entity
+ The `"deny"` state MUST NOT be specified for room IDs under the `"rooms"` object.
+* `"allow"`: Permit sharing presence with the entity
+ The `"allow"` state MUST NOT be specified for entire homeservers under the `"servers"` object.
+
+Sample `m.presence.sharing` account data event:
+```json
+{
+ "share_locally": true,
+ "users": {
+ "@alice:example.com": "allow",
+ "@mallory:example.com": "deny",
+ },
+ "rooms": { "!family-group-chat": "allow" },
+ "servers": { "matrix.org": "deny" }
+}
+```
+
+### Room Presence Sharing Hints
+
+A new room state event is introduced, `m.room.presence_sharing`. This state event contains one field,
+`presence_sharing`, which is a string with two possible values: `"suggest"` and `"forbid"`. If the event is not
+present, the room is treated as though its value is `"forbid"` by default.
+
+Servers MUST NOT include rooms with a `presence_sharing` value of `"forbid"` when they calculate a user's recipient
+user set, even if the user `"allow"`s presence to be shared with the room.
+
+The `m.room.presence_sharing` hint SHOULD be [transferred upon room upgrade][room-upgrades].
+
+#### Presence Sharing Prompts
+
+A new [`account_data`] entry, `m.presence.prompted`, is introduced to improve the user experience for clients with
+presence sharing prompts. To allow users to dismiss a prompt on one client and have this register across all of
+their clients, so that they do not have to answer the prompt several times, the following standard properties are
+used:
+* `users`: An array of [User IDs][mxid-format] (default `[]`)
+* `rooms`: An array of [Room IDs][roomid-format] (default `[]`)
+
+Sample `m.presence.prompted` account data event:
+```json
+{
+ "users": [
+ "@joey:example.com",
+ "@chandler:example.com",
+ ],
+ "rooms": ["!apartment-group-chat"]
+}
+```
+
+Clients implementing presence sharing prompts SHOULD show a prompt resembling "Would you like to share your
+presence with this room?" for a relevant entity, which is the user in an `m.direct` room with **exactly one** other
+joined user or the room itself otherwise, in the following circumstances:
+* The room's `presence_sharing` is set to `"suggest"`
+* The relevant entity is not in the user's corresponding `m.presence.prompted` array or `m.presence.sharing` map
+
+Clients MAY wish to check room predecessor chains to avoid showing previously dismissed prompts in upgraded rooms.
+They SHOULD carry settings over when starting and following a room upgrade. They MUST NOT prompt the user to share
+presence in a room with a `presence_sharing` value of `"forbid"`.
+
+#### Room Defaults
+
+[`POST /_matrix/client/v3/create_room`][cs-createroom] SHOULD use the `preset` parameter to set the
+`m.room.presence_sharing` state event in created rooms to the following template values:
+
+| room creation `preset` | `m.room.presence_sharing` |
+| ---------------------- | ----------------------------------- |
+| `private_chat` | `{ "presence_sharing": "suggest" }` |
+| `trusted_private_chat` | `{ "presence_sharing": "suggest" }` |
+| `public_chat` | `{ "presence_sharing": "forbid" }` |
+
+### Modifications to the [`m.presence` EDU]
+
+The federation [User Presence Update] type is modified to include:
+* An optional map, `recipients`, containing two arrays of [User IDs][mxid-format] belonging to the destination
+ server, `add` and `delete`.
+* A pair of integer identifiers, `stream_id` and `prev_id`, which are unique per `user_id`. These values do not need to
+ be sequential or in any particular order, only unique.
+
+The `add` and `delete` arrays of `recipients` represent an incremental update to a user's recipient user set,
+adding and removing users respectively. A server MUST NOT send updates lacking a populated `add` to a destination
+homeserver after their last user is updated out of the recipient set.
+
+`stream_id` and `prev_id` form a sequence representing the state of the user's recipient user set, similar to the
+behaviour of the [Device List Update] type. `recipients` may only be present if `prev_id` is present. If a user's
+`stream_id` is replaced but no changes are relevant to the receiving homeserver, the sending server uses empty `add`
+and `delete` lists.
+
+`m.presence` EDU (as received by `example.com`):
+```json
+{
+ "content": {
+ "push": [
+ {
+ "currently_active": true,
+ "last_active_ago": 5000,
+ "presence": "online",
+ "status_msg": "Making cupcakes",
+ "user_id": "@john:matrix.org",
+ "recipients": {
+ "add": ["@alice:example.com"],
+ "delete": ["@geoff:example.com"],
+ },
+ "stream_id": 1,
+ "prev_id": 0,
+ }
+ ]
+ },
+ "edu_type": "m.presence"
+}
+```
+
+#### Dispatch Algorithm
+
+The **recipient user set** of a user's presence transition is determined as follows:
+1. Include all members of rooms both **listed as `"allow"`** in the user's `m.presence.sharing` configuration and
+ with an `m.room.presence_sharing` state event with `presence_sharing` set to `"suggest"`. Servers MUST NOT
+ include rooms that do not satisfy this criteria.
+2. Exclude any user IDs with a server name corresponding to **any server listed as `"deny"`** in the user's
+ `m.presence.sharing` configuration.
+3. Include all local users if the user's `m.presence.sharing` configuration has `share_locally` set to `true`.
+ Servers SHOULD only include local users that the sender shares at least one room with.
+4. Include all **users listed as `"allow"`** in the user's `m.presence.sharing` configuration. Servers SHOULD only
+ include users from this list that the sender shares at least one room with.
+5. Exclude any **users listed as `"deny"`** in the user's `m.presence.sharing` configuration.
+
+Determine the delta from the previous recipient user set. If there is no previous state, the entire set is an addition.
+If the recipient user set is left unchanged, emit a presence EDU using only the prior `stream_id` \- no `recipients`, no
+`prev_id`. Otherwise, generate a `stream_id` for the new state. Emit a presence EDU for each destination of the
+recipients in these updates, with `prev_id` set to the last `stream_id` sent to the destination if applicable,
+`stream_id` set according to the new state, and `recipients` populated with the updates for the destination.
+
+#### Inbound Processing
+
+When a server receives a `m.presence` EDU over federation, servers follow these rules for distributing the presence
+change over both `/sync` and `/_matrix/client/v3/presence/{userId}/status`:
+* **`stream_id` missing:** Servers SHOULD distribute the presence transition to every local user that shares a room
+ with the `user_id` of the EDU, following current presence behaviour.
+* **`recipients` missing, `prev_id` missing:** If `stream_id` matches the server's latest known ID, it MUST reuse
+ its current view of the recipient user set to distribute the presence change to users in the set.
+* **`recipients` present, `prev_id` missing:** Servers MUST initialise this as a new set using `recipients` if they
+ have no existing state for the user, and only distribute the presence change to users added by `recipients`.
+* **`recipients` present, `prev_id` present:** Servers MUST apply the delta to the set corresponding to `prev_id`
+ and only distribute the presence change to users in the resulting set, superseding `prev_id` in the process.
+
+If `prev_id` is present but differs from the previous `stream_id`, or `stream_id` is present on its own but
+unrecognised, servers SHOULD query the `GET /_matrix/federation/v1/query/presence_recipients` endpoint on the
+origin server.
+
+### Server-Server Endpoint `GET /_matrix/federation/v1/query/presence_recipients`
+
+Servers that do not recognise a `stream_id` or `prev_id` in an incoming `m.presence` EDU need a way to ask the
+origin server for the user's latest `stream_id` and a snapshot of its recipient user set. This proposal introduces
+a new federation endpoint to address this need. If a server cannot determine the proper recipient user set \- for
+example, if this endpoint returns an error \- it SHOULD be assumed to be empty (`[]`) until the server can fetch
+the full set.
+
+
+
+
+ | Rate limited: |
+ No |
+
+
+ | Requires authentication: |
+ Yes |
+
+
+
+
+#### Request
+
+##### Request parameters
+
+| Name | Type | Description |
+|-----------|----------|----------------------------------------------------------------------------|
+| `user_id` | `string` | **Required:** The user ID to query. Must be local to the queried server. |
+
+#### Responses
+
+| Status | Description |
+|--------|--------------------------------------------------------------------------------------------|
+| `200` | The corresponding user's latest `stream_id` and recipient user set for the sending server. |
+| `404` | The user does not have a recipient set available for the sending server. |
+
+The 404 response uses the same format as in the existing query endpoints.
+
+##### 200 response
+
+| Name | Type | Description |
+|--------------|-----------------------------|----------------------------------------------------------------------------------|
+| `stream_id` | `integer` | **Required:** A unique identifier for the user's current recipient user set. |
+| `recipients` | `[`[`User`][mxid-format]`]` | **Required:** An array of local recipients the user intends to push presence to. |
+
+```json
+{
+ "stream_id": 1,
+ "recipients": [
+ "@jesse:example.com",
+ "@jane:example.com"
+ ]
+}
+```
+
+## Potential issues
+
+### Presence Access
+
+Selective Presence *disables presence by default*. This may complicate future proposals that require publicly
+accessible presence information, and may change the way users interact with presence features. However, as
+previously mentioned, presence should not be public by default. A future proposal may address public, fetchable
+presence (see [Alternatives](#Alternatives)).
+
+### Presence Data "Leaks"
+
+* Presence information may be exposed to unintended or undesirable users by bad-acting servers if any of their
+ users are included in the recipient user set. This proposal is a best-effort approach and cannot combat this.
+* Presence information may be exposed to unintended or undesirable users by the user's own homeserver, for instance
+ if the administrator modifies their account data to trick them.
+* Remote homeservers may deduce parts of users' exclusion lists probabilistically. The scope of this is limited by
+ only sending relevant data to each homeserver.
+* The introduced account data for exclusion lists is sensitive and not encryptable (as in [MSC4483]), but this is
+ information the server would likely know by other means (e.g. [`m.ignored_user_list`])
+
+### Lack of Presence Requests
+
+Prior to [MSC1819], Presence Lists provided for a "presence request" feature. This may be desirable in the future,
+but it is considered out of scope for this proposal.
+
+### Performance
+
+Homeserver operators and implementers may wish to limit the performance impacts of presence, particularly as the
+goal of Selective Presence is to make presence viable for popular use. Potential options for doing so may include:
+* Limiting the ability of users to share presence with rooms above a certain number of members
+* Limiting the number of entities (or total recipient users) users can have in their presence sharing maps
+
+### Presence EDU Batch Sizes
+
+Homeserver implementations or the specification may, in future, limit EDU sizes in the same way PDU sizes are limited.
+This proposal does not specify a strict limit on batch sizes because it is currently unclear what the size limit of EDUs
+may be, so a batch size will need to be specified if this happens. If the limit turns out to be 64KiB, as it is for
+PDUs, and assuming the `status_msg` stays within 255 bytes, you cannot fit more than 250 full 255 byte entities into a
+presence EDU with a single state transition.
+
+## Alternatives
+
+### Pull-based Presence
+
+A pull-based system leads to unnecessary requests over federation on polling intervals when no presence updates are
+available, creating inefficiencies that may be intolerable for mainstream use and still requiring access control to
+achieve any privacy benefits. An auxiliary fetchable presence system is considered complementary follow-up work to
+allow users to make their presence public.
+
+### Receiver Resolution
+
+Instead of sending a finalised list of recipient users to remote servers, the user's preferences (allowed rooms and
+users, denied users) could be sent over federation. This proposal uses sender-side user resolution to avoid sending
+a "block list" to third parties, and to keep resolution consistent with the sending homeserver's state.
+
+### Entity Selection Affordances
+
+Servers could be permitted in the inclusion list, and rooms could be permitted in the exclusion list. The authors
+of this proposal found no reason for doing so. In organisation environments where it may be desired to share
+presence with an entire homeserver, users are almost certainly on the same local homeserver, where `share_locally`
+applies, or share a room with everyone in the organisation, which the users can set as `"allow"`. Excluding a room
+has no practical benefits as users can simply not include it in the configuration.
+
+Globs were prohibited in presence sharing maps to avoid introducing security issues for servers running glob parsing on
+arbitrary user-provided strings, and because users are not typically namespaced beyond servers in a way that would be
+suitable for glob selection.
+
+### Entity Resolution Ordering
+
+The inclusion and exclusion lists could be applied in different orders; for example, if a user of a homeserver is set to
+`"allow"`, and the homeserver is set to `"deny"`, should the user become an exception, or should the whole homeserver be
+prevented from receiving the presence? It was decided that users should always be the overriding rule, otherwise a user
+wouldn't explicitly `"allow"` them, and only allowing one other entity type for either option prevents conflicts.
+
+### Per-Room Hint Following
+
+In this proposal, the `"allow"` state means "follow the room's hint state." Instead, the user's configuration could
+be decoupled from room hints, meaning users could broadcast their presence to all users of a room regardless of
+whether the room administrators have enabled the hint. This can create issues in large rooms and conflicts with the
+recommendation purpose of the hints system.
+
+Allowing room administrators to suggest that their members share presence means users can still see presence for
+members of small rooms (assuming they opt in to this behaviour) without explicitly creating user lists. These are
+the rooms where presence matters most: small groups of friends, organisation environments, etc.
+
+Only allowing users to follow hints via `"allow"` means a `"forbid"` hint state explicitly forbids presence sharing
+for all users of a room. This allows room administrators to retroactively *disable* presence sharing for rooms as
+they grow; for example, if a previously private room grows to be public and contain many members, a room
+administrator may wish to disable presence sharing in the room.
+
+### `m.room.presence_sharing` states
+
+There are multiple potential states for room hints, and just as many potential defaults. It was ultimately
+determined that this proposal should only specify the actual states of `"suggest"` or `"forbid"`, leaving the
+decision of when to ask users if they would like to enable presence up to the clients.
+
+### Room Account Data
+
+It was proposed that a user's `m.presence.sharing` `"rooms"` configuration could live in room account data, but
+this proposal opted against doing so to avoid fragmenting the configuration between different sources.
+
+### Fallback Behaviours
+
+#### Client-Server Sync
+
+If a server were to receive an EDU with no `stream_id`, it could either ignore the EDU, or sync it to clients of its
+local users that share a room with the `user_id` in the EDU, as is the current behaviour. To preserve backwards
+compatibility for older servers unaware of the `recipients` system, this proposal specifies that the current behaviour
+should be invoked for these EDUs. The authors of this proposal intend for this fallback behaviour to be removed when a
+sufficient proportion of the network has updated to use Selective Presence, which will entirely remove the excess
+traffic of publicly broadcasted presence and allow implementers to simplify processing on receiving homeservers.
+
+#### Server-Server Dispatch
+
+If a user's `account_data` were missing `m.presence.sharing` configuration, the sending server could either invoke the
+current behaviour by sending a presence EDU with no `stream_id`, or avoid sending presence for the user entirely. While
+backwards compatibility is important where it is possible, allowing *clients* to induce this behaviour intentionally
+would create a user-controlled bypass for Selective Presence altogether, defeating its purpose. Therefore, this proposal
+opts to forbid sending presence for users that have not set an `m.presence.sharing` configuration.
+
+## Security considerations
+
+This proposal does not introduce any new security considerations as far as its authors are aware.
+
+## Future work
+
+The following complementary proposals are planned:
+* Increasing presence TTLs and improving batching behaviour
+* Fetchable presence, possibly involving [MSC4133]'s profile key-value fields
+* Sliding Sync extension for presence
+* Presence Requests
+
+## Unstable prefix
+
+| Stable identifier | Purpose | Unstable identifier |
+| ------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ |
+| `recipients` | Recipient users to add and delete in federation presence EDU | `org.continuwuity.presence_v2.msc4495.recipients` |
+| `stream_id` | Current recipient user set identifier federation presence EDU | `org.continuwuity.presence_v2.msc4495.stream_id` |
+| `prev_id` | Previous recipient user set identifier in federation presence EDU | `org.continuwuity.presence_v2.msc4495.prev_id` |
+| `m.presence.sharing` | `account_data` entry for presence sharing config | `org.continuwuity.presence_v2.msc4495.presence.sharing` |
+| `m.presence.prompted` | `account_data` entry for persisting presence hint prompt responses | `org.continuwuity.presence_v2.msc4495.presence.prompted` |
+| `m.room.presence_sharing` | Room state event for presence sharing hint | `org.continuwuity.presence_v2.msc4495.room.presence_sharing` |
+
+Servers may advertise support for Selective Presence by listing `org.continuwuity.presence_v2.msc4495` in the
+`unstable_features` section of the response to [`GET /_matrix/client/versions`][cs-versions].
+
+The stable endpoint `/_matrix/federation/v1/query/presence_recipients` will use the unstable identifier
+`/_matrix/federation/unstable/org.continuwuity.presence_v2.msc4495/query/presence_recipients`.
+
+Once this proposal completes FCP, servers may advertise support for the stable identifiers by listing
+`org.continuwuity.presence_v2.msc4495.stable` in `unstable_features`; clients may use this while they
+are waiting for the server to adopt a version of the spec that includes it.
+
+## Dependencies
+
+None.
+
+[^1]: Synapse has had a meta-issue open about improving presence performance for 5 years: [#9478]
+[^2]: Since 2018, homeserver operators have had performance concerns related to presence, and even raised them
+ as bugs in Synapse. [#3971] [#9339]
+
+[#3971]: https://github.com/matrix-org/synapse/issues/3971
+[#4417]: https://github.com/matrix-org/synapse/issues/4417
+[#9339]: https://github.com/matrix-org/synapse/issues/9339
+[#9478]: https://github.com/matrix-org/synapse/issues/9478
+[MSC1819]: https://github.com/matrix-org/matrix-spec-proposals/pull/1819
+[MSC4133]: https://github.com/matrix-org/matrix-spec-proposals/pull/4133
+[MSC4325]: https://github.com/matrix-org/matrix-spec-proposals/pull/4325
+[MSC4483]: https://github.com/matrix-org/matrix-spec-proposals/pull/4483
+[presence-v1-privacy]: https://spec.matrix.org/v1.17/client-server-api/#security-considerations-4
+[`m.presence` EDU]: https://spec.matrix.org/v1.18/server-server-api/#definition-mpresence
+[User Presence Update]: https://spec.matrix.org/v1.18/server-server-api/#definition-mpresence_user-presence-update
+[Device List Update]: https://spec.matrix.org/v1.18/server-server-api/#definition-mdevice_list_update_device-list-update
+[mxid-format]: https://spec.matrix.org/v1.18/appendices/#user-identifiers
+[roomid-format]: https://spec.matrix.org/v1.18/appendices/#room-ids
+[servername-format]: https://spec.matrix.org/v1.18/appendices/#server-name
+[`account_data`]: https://spec.matrix.org/v1.18/client-server-api/#client-config
+[cs-versions]: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientversions
+[cs-createroom]: https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3createroom
+[`m.ignored_user_list`]: https://spec.matrix.org/v1.18/client-server-api/#mignored_user_list
+[room-upgrades]: https://spec.matrix.org/v1.18/client-server-api/#server-behaviour-21