diff --git a/changelog.d/9425.bugfix b/changelog.d/9425.bugfix
new file mode 100644
index 0000000000000000000000000000000000000000..f5b8857cdb660cbec44f6f763437d337e5ef8654
--- /dev/null
+++ b/changelog.d/9425.bugfix
@@ -0,0 +1 @@
+Fix a long-standing bug in the deduplication of old presence, resulting in no deduplication.
\ No newline at end of file
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 7ba22d511f33cbdaae233a7d00c3b56b33851d25..ed90b5d4571f0b11f0c2520287fcf2552c09d9f0 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -349,10 +349,13 @@ class PresenceHandler(BasePresenceHandler):
                 [self.user_to_current_state[user_id] for user_id in unpersisted]
             )
 
-    async def _update_states(self, new_states):
+    async def _update_states(self, new_states: Iterable[UserPresenceState]) -> None:
         """Updates presence of users. Sets the appropriate timeouts. Pokes
         the notifier and federation if and only if the changed presence state
         should be sent to clients/servers.
+
+        Args:
+            new_states: The new user presence state updates to process.
         """
         now = self.clock.time_msec()
 
@@ -368,7 +371,7 @@ class PresenceHandler(BasePresenceHandler):
             new_states_dict = {}
             for new_state in new_states:
                 new_states_dict[new_state.user_id] = new_state
-            new_state = new_states_dict.values()
+            new_states = new_states_dict.values()
 
             for new_state in new_states:
                 user_id = new_state.user_id