diff --git a/keyserver/src/scripts/test-threadstore-reductions.js b/keyserver/src/scripts/test-threadstore-reductions.js
--- a/keyserver/src/scripts/test-threadstore-reductions.js
+++ b/keyserver/src/scripts/test-threadstore-reductions.js
@@ -1,7 +1,14 @@
 // @flow
 
+import invariant from 'invariant';
+
 import ashoat from 'lib/facts/ashoat.js';
 import type { RawMessageInfo } from 'lib/types/message-types.js';
+import type {
+  ThreadPermission,
+  ThreadPermissionsInfo,
+  ThreadRolePermissionsBlob,
+} from 'lib/types/thread-permission-types.js';
 import { threadTypes } from 'lib/types/thread-types-enum.js';
 import type { RawThreadInfos } from 'lib/types/thread-types.js';
 
@@ -33,6 +40,14 @@
     "after filtering out old sidebars, Ashoat's ThreadStore is " +
       `${withoutOldSidebarsBytes} bytes large`,
   );
+
+  const improvedEncoding = improveEncoding(threadInfos);
+  const improvedEncodingString = JSON.stringify(improvedEncoding);
+  const improvedEncodingBytes = new Blob([improvedEncodingString]).size;
+  console.log(
+    "after improving encoding, Ashoat's ThreadStore is " +
+      `${improvedEncodingBytes} bytes large`,
+  );
 }
 
 function filterOutOldSidebars(
@@ -62,4 +77,127 @@
   return filtered;
 }
 
+function improveEncoding(threadInfos: RawThreadInfos) {
+  const simplifiedThreadStore = {};
+  for (const threadID in threadInfos) {
+    const threadInfo = threadInfos[threadID];
+    const newRoles = {};
+    for (const roleID in threadInfo.roles) {
+      const role = threadInfo.roles[roleID];
+      newRoles[roleID] = {
+        ...role,
+        permissions: improveThreadRolePermissionsBlobEncoding(role.permissions),
+      };
+    }
+    const smallerThreadInfo = {
+      ...threadInfo,
+      roles: newRoles,
+      members: threadInfo.members.map(member => {
+        const { permissions } = member;
+        if (!permissions) {
+          return member;
+        }
+        return {
+          ...member,
+          permissions: improveThreadPermissionsBlobEncoding(member.permissions),
+        };
+      }),
+      currentUser: {
+        ...threadInfo.currentUser,
+        permissions: improveThreadPermissionsBlobEncoding(
+          threadInfo.currentUser.permissions,
+        ),
+      },
+    };
+    simplifiedThreadStore[threadID] = smallerThreadInfo;
+  }
+  return simplifiedThreadStore;
+}
+
+const smallerPermissionConstants = {
+  ['know_of']: 'a',
+  ['membership']: 'b',
+  ['visible']: 'c',
+  ['voiced']: 'd',
+  ['edit_entries']: 'e',
+  ['edit_thread']: 'f',
+  ['edit_thread_description']: 'g',
+  ['edit_thread_color']: 'h',
+  ['delete_thread']: 'i',
+  ['create_subthreads']: 'j',
+  ['create_sidebars']: 'k',
+  ['join_thread']: 'l',
+  ['edit_permissions']: 'm',
+  ['add_members']: 'n',
+  ['remove_members']: 'o',
+  ['change_role']: 'p',
+  ['leave_thread']: 'q',
+  ['react_to_message']: 'r',
+  ['edit_message']: 's',
+  ['edit_thread_avatar']: 't',
+  ['manage_pins']: 'u',
+  ['manage_invite_links']: 'v',
+};
+function improveThreadPermissionsBlobEncoding(blob: ThreadPermissionsInfo) {
+  const newBlob = {};
+  for (const permission in blob) {
+    const permissionTyped: ThreadPermission = (permission: any);
+    const oldValue = blob[permissionTyped].value;
+    if (!oldValue) {
+      continue;
+    }
+    const newKey = smallerPermissionConstants[permission];
+    invariant(newKey, `no newKey for ${permission}!`);
+    newBlob[newKey] = 1;
+  }
+  return newBlob;
+}
+
+const smallerThreadPermissionPropagationPrefixes = {
+  ['descendant_']: '1',
+  ['child_']: '2',
+};
+const smallerThreadPermissionFilterPrefixes = {
+  ['open_']: '3',
+  ['toplevel_']: '4',
+  ['opentoplevel_']: '5',
+};
+function improveThreadRolePermissionsBlobEncoding(
+  blob: ThreadRolePermissionsBlob,
+) {
+  const newBlob = {};
+  for (const permission in blob) {
+    const oldValue = blob[permission];
+    if (!oldValue) {
+      continue;
+    }
+
+    let newKey = '';
+    let oldKey = permission;
+
+    for (const prefix in smallerThreadPermissionPropagationPrefixes) {
+      if (!oldKey.startsWith(prefix)) {
+        continue;
+      }
+      oldKey = oldKey.substr(prefix.length);
+      newKey += smallerThreadPermissionPropagationPrefixes[prefix];
+    }
+
+    for (const prefix in smallerThreadPermissionFilterPrefixes) {
+      if (!oldKey.startsWith(prefix)) {
+        continue;
+      }
+      oldKey = oldKey.substr(prefix.length);
+      newKey += smallerThreadPermissionFilterPrefixes[prefix];
+    }
+
+    const newPermConstant = smallerPermissionConstants[oldKey];
+    invariant(newPermConstant, `no newPermConstant for ${oldKey}!`);
+    newKey += newPermConstant;
+
+    newBlob[newKey] = 1;
+  }
+  return newBlob;
+}
+
 main([testThreadStoreReductions]);