diff --git a/docs/releases.md b/docs/releases.md
index eebc595e..c995945c 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -1151,3 +1151,14 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
 **Additional languages:**
 
 * Swedish (thanks to [@hellbown](https://hosted.weblate.org/user/hellbown/))
+
+## ntfy server v2.3.1
+
+This release disables server-initiated polling of iOS devices entirely, thereby eliminating the thundering herd problem
+on ntfy.sh that we observe every 20 minutes. The polling was never strictly necessary, and has actually caused duplicate
+delivery issues as well, so disabling it should not have any negative effects. iOS users, please reach out via Discord
+or Matrix if there are issues.
+
+**Bug fixes + maintenance:**
+
+* Disable iOS polling entirely ([#677](https://github.com/binwiederhier/ntfy/issues/677))
diff --git a/server/server.go b/server/server.go
index 075d0756..c86307d2 100644
--- a/server/server.go
+++ b/server/server.go
@@ -1529,8 +1529,14 @@ func (s *Server) runFirebaseKeepaliver() {
 		select {
 		case <-time.After(s.config.FirebaseKeepaliveInterval):
 			s.sendToFirebase(v, newKeepaliveMessage(firebaseControlTopic))
-		case <-time.After(s.config.FirebasePollInterval):
-			s.sendToFirebase(v, newKeepaliveMessage(firebasePollTopic))
+		/*
+			FIXME: Disable iOS polling entirely for now due to thundering herd problem (see #677)
+			       To solve this, we'd have to shard the iOS poll topics to spread out the polling evenly.
+			       Given that it's not really necessary to poll, turning it off for now should not have any impact.
+
+			case <-time.After(s.config.FirebasePollInterval):
+				s.sendToFirebase(v, newKeepaliveMessage(firebasePollTopic))
+		*/
 		case <-s.closeChan:
 			return
 		}