diff --git a/keyserver/src/database/migration-config.js b/keyserver/src/database/migration-config.js
--- a/keyserver/src/database/migration-config.js
+++ b/keyserver/src/database/migration-config.js
@@ -5,6 +5,7 @@
 import { policyTypes } from 'lib/facts/policies.js';
 
 import { dbQuery, SQL } from '../database/database.js';
+import { processMessagesInDBForSearch } from '../database/search-utils.js';
 import { updateRolesAndPermissionsForAllThreads } from '../updaters/thread-permission-updaters.js';
 
 const migrations: $ReadOnlyMap<number, () => Promise<void>> = new Map([
@@ -235,6 +236,7 @@
       );
     },
   ],
+  [22, processMessagesInDBForSearch],
 ]);
 const newDatabaseVersion: number = Math.max(...migrations.keys());
 
diff --git a/keyserver/src/database/search-utils.js b/keyserver/src/database/search-utils.js
--- a/keyserver/src/database/search-utils.js
+++ b/keyserver/src/database/search-utils.js
@@ -8,7 +8,7 @@
 import { dbQuery, SQL } from '../database/database.js';
 
 async function processMessagesForSearch(
-  messages: $ReadOnlyArray<RawMessageInfo>,
+  messages: $ReadOnlyArray<RawMessageInfo | ProcessedForSearchRow>,
 ): Promise<void> {
   const processedMessages = [];
 
@@ -45,4 +45,65 @@
   `);
 }
 
-export { processMessagesForSearch };
+type ProcessedForSearchRowText = {
+  +type: 0,
+  +id: string,
+  +text: string,
+};
+type ProcessedForSearchRowEdit = {
+  +type: 20,
+  +id: string,
+  +targetMessageID: string,
+  +text: string,
+};
+type ProcessedForSearchRow =
+  | ProcessedForSearchRowText
+  | ProcessedForSearchRowEdit;
+
+function processRowsForSearch(
+  rows: $ReadOnlyArray<any>,
+): $ReadOnlyArray<ProcessedForSearchRow> {
+  const results = [];
+  for (const row of rows) {
+    if (row.type === messageTypes.TEXT) {
+      results.push({ type: row.type, id: row.id, text: row.content });
+    } else if (row.type === messageTypes.EDIT_MESSAGE) {
+      results.push({
+        type: row.type,
+        id: row.id,
+        targetMessageID: row.target_message,
+        text: row.content,
+      });
+    }
+  }
+  return results;
+}
+
+const pageSize = 1001;
+
+async function processMessagesInDBForSearch(): Promise<void> {
+  let lastID = 0;
+  let messages = [];
+
+  do {
+    [messages] = await dbQuery(SQL`
+      SELECT id, type, content, target_message
+      FROM messages
+      WHERE (type = ${messageTypes.TEXT} OR type = ${messageTypes.EDIT_MESSAGE})
+        AND id > ${lastID}
+      ORDER BY id
+      LIMIT ${pageSize}
+    `);
+
+    const truncatedMessages =
+      messages.length < pageSize ? messages : messages.slice(0, -1);
+
+    const processedRows = processRowsForSearch(truncatedMessages);
+
+    await processMessagesForSearch(processedRows);
+
+    lastID = truncatedMessages[truncatedMessages.length - 1].id;
+  } while (messages.length === pageSize);
+}
+
+export { processMessagesForSearch, processMessagesInDBForSearch };