diff --git a/keyserver/src/cron/cron.js b/keyserver/src/cron/cron.js
--- a/keyserver/src/cron/cron.js
+++ b/keyserver/src/cron/cron.js
@@ -23,6 +23,8 @@
 import { deleteInaccessibleThreads } from '../deleters/thread-deleters.js';
 import { deleteExpiredUpdates } from '../deleters/update-deleters.js';
 import { deleteUnassignedUploads } from '../deleters/upload-deleters.js';
+import { fetchCallUpdateOlmAccount } from '../updaters/olm-account-updater.js';
+import { validateAccountPrekey } from '../utils/olm-utils.js';
 
 if (cluster.isMaster) {
   schedule.scheduleJob(
@@ -90,4 +92,16 @@
       }
     },
   );
+
+  schedule.scheduleJob(
+    '0 0 * * *', // every day at midnight in the keyserver's timezone
+    async () => {
+      try {
+        await fetchCallUpdateOlmAccount('content', validateAccountPrekey);
+        await fetchCallUpdateOlmAccount('notifications', validateAccountPrekey);
+      } catch (e) {
+        console.warn('encountered error while trying to validate prekeys', e);
+      }
+    },
+  );
 }
diff --git a/keyserver/src/utils/olm-utils.js b/keyserver/src/utils/olm-utils.js
--- a/keyserver/src/utils/olm-utils.js
+++ b/keyserver/src/utils/olm-utils.js
@@ -12,6 +12,9 @@
   +pickledAccount: string,
 };
 
+const maxPublishedPrekeyAge = 30 * 24 * 60 * 60 * 1000;
+const maxOldPrekeyAge = 24 * 60 * 60 * 1000;
+
 async function createPickledOlmAccount(): Promise<PickledOlmAccount> {
   await olm.init();
   const account = new olm.Account();
@@ -48,4 +51,31 @@
   return cachedOLMUtility;
 }
 
-export { createPickledOlmAccount, getOlmUtility, unpickleOlmAccount };
+async function validateAccountPrekey(account: OlmAccount): Promise<void> {
+  const currentDate = new Date();
+  const lastPrekeyPublishDate = new Date(account.last_prekey_publish_time());
+
+  const prekeyPublished = !account.unpublished_prekey();
+  if (
+    prekeyPublished &&
+    currentDate - lastPrekeyPublishDate > maxPublishedPrekeyAge
+  ) {
+    // If there is no prekey or the current prekey is older than month
+    // we need to generate new one.
+    account.generate_prekey();
+  }
+
+  if (
+    prekeyPublished &&
+    currentDate - lastPrekeyPublishDate >= maxOldPrekeyAge
+  ) {
+    account.forget_old_prekey();
+  }
+}
+
+export {
+  createPickledOlmAccount,
+  getOlmUtility,
+  unpickleOlmAccount,
+  validateAccountPrekey,
+};