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,9 @@
 import { deleteInaccessibleThreads } from '../deleters/thread-deleters.js';
 import { deleteExpiredUpdates } from '../deleters/update-deleters.js';
 import { deleteUnassignedUploads } from '../deleters/upload-deleters.js';
+import { fetchKeyserverOlmAccount } from '../fetchers/olm-account-fetcher.js';
+import { updateOlmAccount } from '../updaters/olm-account-updater.js';
+import { validateAccountPrekey } from '../utils/olm-utils.js';
 
 if (cluster.isMaster) {
   schedule.scheduleJob(
@@ -90,4 +93,38 @@
       }
     },
   );
+
+  schedule.scheduleJob(
+    '0 0 * * *', // every day at midnight in the keyserver's timezone
+    async () => {
+      try {
+        const [
+          { picklingKey: primaryPicklingKey, account: primaryAccount },
+          {
+            picklingKey: notificationsPicklingKey,
+            account: notificationsAccount,
+          },
+        ] = await Promise.all([
+          fetchKeyserverOlmAccount(true),
+          fetchKeyserverOlmAccount(false),
+        ]);
+
+        await Promise.all([
+          validateAccountPrekey(primaryAccount),
+          validateAccountPrekey(notificationsAccount),
+        ]);
+
+        await Promise.all([
+          updateOlmAccount(primaryAccount, primaryPicklingKey, true),
+          updateOlmAccount(
+            notificationsAccount,
+            notificationsPicklingKey,
+            false,
+          ),
+        ]);
+      } 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
@@ -48,4 +48,36 @@
   return cachedOLMUtility;
 }
 
-export { createPickledOlmAccount, getOlmUtility, unpicklePickledOlmAccount };
+async function validateAccountPrekey(account: OlmAccount): Promise<void> {
+  const prekey = JSON.parse(account.prekey());
+
+  const hasPrekey = Object.keys(prekey.curve25519).length !== 0;
+  const prekeyPublished = account.last_prekey_publish_time() !== 0;
+
+  const currentDate = new Date();
+  const lastPrekeyPublishDate = new Date(account.last_prekey_publish_time());
+
+  if (
+    !hasPrekey ||
+    (prekeyPublished &&
+      currentDate.getMonth() - lastPrekeyPublishDate.getMonth() > 0)
+  ) {
+    // 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.getDay() - lastPrekeyPublishDate.getDay() > 0
+  ) {
+    account.forget_old_prekey();
+  }
+}
+
+export {
+  createPickledOlmAccount,
+  getOlmUtility,
+  unpicklePickledOlmAccount,
+  validateAccountPrekey,
+};