diff --git a/keyserver/src/push/rescind.js b/keyserver/src/push/rescind.js
--- a/keyserver/src/push/rescind.js
+++ b/keyserver/src/push/rescind.js
@@ -5,7 +5,7 @@
 import type { FirebaseError } from 'firebase-admin';
 import invariant from 'invariant';
 
-import { prepareEncryptedAndroidSilentNotifications } from 'lib/push/crypto.js';
+import { createAndroidNotificationRescind } from 'lib/push/android-notif-creators.js';
 import type { PlatformDetails } from 'lib/types/device-types.js';
 import type {
   NotificationTargetDevice,
@@ -375,29 +375,17 @@
   devices: $ReadOnlyArray<NotificationTargetDevice>,
 ): Promise<$ReadOnlyArray<TargetedAndroidNotification>> {
   threadID = await validateOutput(platformDetails, tID, threadID);
-  const { codeVersion } = platformDetails;
-
-  const notification = {
-    data: {
+  return await createAndroidNotificationRescind(
+    encryptedNotifUtilsAPI,
+    {
+      senderDeviceDescriptor: { keyserverID },
       badge: unreadCount.toString(),
-      rescind: 'true',
+      platformDetails,
       rescindID: notifID,
-      setUnreadStatus: 'true',
       threadID,
     },
-  };
-  const targetedRescinds = await conditionallyEncryptNotification(
-    encryptedNotifUtilsAPI,
-    { keyserverID },
-    notification,
-    codeVersion,
     devices,
-    prepareEncryptedAndroidSilentNotifications,
   );
-  return targetedRescinds.map(targetedRescind => ({
-    ...targetedRescind,
-    priority: 'normal',
-  }));
 }
 
 export { rescindPushNotifs };
diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js
--- a/keyserver/src/push/send.js
+++ b/keyserver/src/push/send.js
@@ -16,8 +16,8 @@
   type AndroidNotifInputData,
   androidNotifInputDataValidator,
   createAndroidVisualNotification,
+  createAndroidBadgeOnlyNotification,
 } from 'lib/push/android-notif-creators.js';
-import { prepareEncryptedAndroidSilentNotifications } from 'lib/push/crypto.js';
 import {
   type WebNotifInputData,
   webNotifInputDataValidator,
@@ -1601,39 +1601,21 @@
   if (androidVersionsToTokens) {
     for (const [versionKey, deviceInfos] of androidVersionsToTokens) {
       const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
-      const notificationData = {
-        badge: unreadCount.toString(),
-        badgeOnly: '1',
-      };
-      const notification = {
-        data: { ...notificationData },
-      };
       const preparePromise: Promise<PreparePushResult[]> = (async () => {
-        let targetedNotifications: $ReadOnlyArray<TargetedAndroidNotification>;
-        const priority = 'normal';
-        if (codeVersion > 222) {
-          const notificationsArray =
-            await prepareEncryptedAndroidSilentNotifications(
-              encryptedNotifUtilsAPI,
-              { keyserverID },
-              deviceInfos,
-              notification,
-            );
-          targetedNotifications = notificationsArray.map(
-            ({ notification: notif, deliveryID, encryptionOrder }) => ({
-              priority,
-              notification: notif,
-              deliveryID,
-              encryptionOrder,
-            }),
+        const targetedNotifications: $ReadOnlyArray<TargetedAndroidNotification> =
+          await createAndroidBadgeOnlyNotification(
+            encryptedNotifUtilsAPI,
+            {
+              senderDeviceDescriptor: { keyserverID },
+              badge: unreadCount.toString(),
+              platformDetails: {
+                codeVersion,
+                stateVersion,
+                platform: 'android',
+              },
+            },
+            deviceInfos,
           );
-        } else {
-          targetedNotifications = deviceInfos.map(({ deliveryID }) => ({
-            priority,
-            deliveryID,
-            notification,
-          }));
-        }
         return targetedNotifications.map(targetedNotification => ({
           notification: targetedNotification,
           platform: 'android',
diff --git a/lib/push/android-notif-creators.js b/lib/push/android-notif-creators.js
--- a/lib/push/android-notif-creators.js
+++ b/lib/push/android-notif-creators.js
@@ -1,9 +1,16 @@
 // @flow
 
+import invariant from 'invariant';
 import t, { type TInterface } from 'tcomb';
 
-import { prepareEncryptedAndroidVisualNotifications } from './crypto.js';
-import { hasMinCodeVersion } from '../shared/version-utils.js';
+import {
+  prepareEncryptedAndroidVisualNotifications,
+  prepareEncryptedAndroidSilentNotifications,
+} from './crypto.js';
+import {
+  hasMinCodeVersion,
+  FUTURE_CODE_VERSION,
+} from '../shared/version-utils.js';
 import type { PlatformDetails } from '../types/device-types.js';
 import { messageTypes } from '../types/message-types-enum.js';
 import {
@@ -19,6 +26,7 @@
   type SenderDeviceDescriptor,
   senderDeviceDescriptorValidator,
   type EncryptedNotifUtilsAPI,
+  type AndroidBadgeOnlyNotification,
 } from '../types/notif-types.js';
 import { tID, tPlatformDetails, tShape } from '../utils/validation-utils.js';
 
@@ -250,5 +258,149 @@
     ...targetedNotifsWithoutMessageInfos,
   ];
 }
+type AndroidNotificationRescindInputData = {
+  +senderDeviceDescriptor: SenderDeviceDescriptor,
+  +threadID: string,
+  +rescindID?: string,
+  +badge?: string,
+  +platformDetails: PlatformDetails,
+};
+
+async function createAndroidNotificationRescind(
+  encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  inputData: AndroidNotificationRescindInputData,
+  devices: $ReadOnlyArray<NotificationTargetDevice>,
+): Promise<$ReadOnlyArray<TargetedAndroidNotification>> {
+  const {
+    senderDeviceDescriptor,
+    platformDetails,
+    threadID,
+    rescindID,
+    badge,
+  } = inputData;
+
+  let notification = {
+    data: {
+      rescind: 'true',
+      setUnreadStatus: 'true',
+      threadID,
+    },
+  };
+
+  invariant(
+    (rescindID && badge) ||
+      hasMinCodeVersion(platformDetails, { native: FUTURE_CODE_VERSION }),
+    'thick thread rescind not support for this client version',
+  );
+
+  if (rescindID && badge) {
+    notification = {
+      ...notification,
+      data: {
+        ...notification.data,
+        badge,
+        rescindID,
+      },
+    };
+  }
+
+  const shouldBeEncrypted = hasMinCodeVersion(platformDetails, { native: 233 });
+  if (!shouldBeEncrypted) {
+    return devices.map(({ deliveryID }) => ({
+      notification,
+      deliveryID,
+      priority: 'normal',
+    }));
+  }
+
+  const notifications = await prepareEncryptedAndroidSilentNotifications(
+    encryptedNotifUtilsAPI,
+    senderDeviceDescriptor,
+    devices,
+    notification,
+  );
+
+  return notifications.map(({ deliveryID, notification: notif }) => ({
+    deliveryID,
+    notification: notif,
+    priority: 'normal',
+  }));
+}
+
+type SenderDescriptorWithPlatformDetails = {
+  +senderDeviceDescriptor: SenderDeviceDescriptor,
+  +platformDetails: PlatformDetails,
+};
+
+type AndroidBadgeOnlyNotificationInputData = $ReadOnly<
+  | {
+      ...SenderDescriptorWithPlatformDetails,
+      +badge: string,
+    }
+  | { ...SenderDescriptorWithPlatformDetails, +threadID: string },
+>;
+
+async function createAndroidBadgeOnlyNotification(
+  encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+  inputData: AndroidBadgeOnlyNotificationInputData,
+  devices: $ReadOnlyArray<NotificationTargetDevice>,
+): Promise<$ReadOnlyArray<TargetedAndroidNotification>> {
+  const { senderDeviceDescriptor, platformDetails, badge, threadID } =
+    inputData;
+
+  invariant(
+    (!threadID && badge) ||
+      hasMinCodeVersion(platformDetails, { native: FUTURE_CODE_VERSION }),
+    'thick thread badge updates not support for this client version',
+  );
+
+  let notificationData = { badgeOnly: '1' };
+  if (badge) {
+    notificationData = {
+      ...notificationData,
+      badge,
+    };
+  } else {
+    invariant(
+      threadID,
+      'Either badge or threadID must be present in badge only notif',
+    );
+    notificationData = {
+      ...notificationData,
+      threadID,
+    };
+  }
+
+  const notification: AndroidBadgeOnlyNotification = { data: notificationData };
+  const shouldBeEncrypted = hasMinCodeVersion(platformDetails, { native: 222 });
+
+  if (!shouldBeEncrypted) {
+    return devices.map(({ deliveryID }) => ({
+      notification,
+      deliveryID,
+      priority: 'normal',
+    }));
+  }
+
+  const notifications = await prepareEncryptedAndroidSilentNotifications(
+    encryptedNotifUtilsAPI,
+    senderDeviceDescriptor,
+    devices,
+    notification,
+  );
+
+  return notifications.map(
+    ({ notification: notif, deliveryID, encryptionOrder }) => ({
+      priority: 'normal',
+      notification: notif,
+      deliveryID,
+      encryptionOrder,
+    }),
+  );
+}
 
-export { createAndroidVisualNotification };
+export {
+  createAndroidVisualNotification,
+  createAndroidBadgeOnlyNotification,
+  createAndroidNotificationRescind,
+};
diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js
--- a/lib/types/notif-types.js
+++ b/lib/types/notif-types.js
@@ -130,33 +130,48 @@
   }>,
 };
 
+type AndroidThinThreadRescindPayload = {
+  +badge: string,
+  +rescind: 'true',
+  +rescindID?: string,
+  +setUnreadStatus: 'true',
+  +threadID: string,
+  +encryptionFailed?: string,
+};
+
+type AndroidThickThreadRescindPayload = {
+  +rescind: 'true',
+  +setUnreadStatus: 'true',
+  +threadID: string,
+  +encryptionFailed?: string,
+};
+
 export type AndroidNotificationRescind = {
-  +data: $ReadOnly<{
-    ...
-      | {
-          +badge: string,
-          +rescind: 'true',
-          +rescindID: string,
-          +setUnreadStatus: 'true',
-          +threadID: string,
-          +encryptionFailed?: string,
-        }
-      | EncryptedThinThreadPayload
-      | EncryptedThickThreadPayload,
-  }>,
+  +data:
+    | AndroidThinThreadRescindPayload
+    | AndroidThickThreadRescindPayload
+    | EncryptedThinThreadPayload
+    | EncryptedThickThreadPayload,
+};
+
+type AndroidKeyserverBadgeOnlyPayload = {
+  +badge: string,
+  +badgeOnly: '1',
+  +encryptionFailed?: string,
+};
+
+type AndroidThickThreadBadgeOnlyPayload = {
+  +threadID: string,
+  +badgeOnly: '1',
+  +encryptionFailed?: string,
 };
 
 export type AndroidBadgeOnlyNotification = {
-  +data: $ReadOnly<{
-    ...
-      | {
-          +badge: string,
-          +badgeOnly: '1',
-          +encryptionFailed?: string,
-        }
-      | EncryptedThinThreadPayload
-      | EncryptedThickThreadPayload,
-  }>,
+  +data:
+    | AndroidKeyserverBadgeOnlyPayload
+    | AndroidThickThreadBadgeOnlyPayload
+    | EncryptedThinThreadPayload
+    | EncryptedThickThreadPayload,
 };
 
 type AndroidNotificationWithPriority =