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
@@ -277,6 +277,17 @@
   ],
   [23, updateRolesAndPermissionsForAllThreads],
   [24, updateRolesAndPermissionsForAllThreads],
+  [
+    25,
+    async () => {
+      await dbQuery(SQL`
+        ALTER TABLE messages
+          ADD COLUMN IF NOT EXISTS pinned tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
+          ADD COLUMN IF NOT EXISTS pin_time bigint(20) DEFAULT NULL,
+          ADD INDEX IF NOT EXISTS thread_pinned (thread, pinned);
+      `);
+    },
+  ],
 ]);
 const newDatabaseVersion: number = Math.max(...migrations.keys());
 
diff --git a/keyserver/src/database/setup-db.js b/keyserver/src/database/setup-db.js
--- a/keyserver/src/database/setup-db.js
+++ b/keyserver/src/database/setup-db.js
@@ -89,7 +89,9 @@
         content mediumtext COLLATE utf8mb4_bin,
         time bigint(20) NOT NULL,
         creation varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
-        target_message bigint(20) DEFAULT NULL
+        target_message bigint(20) DEFAULT NULL,
+        pinned tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
+        pin_time bigint(20) DEFAULT NULL
       ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
 
       CREATE TABLE notifications (
@@ -279,7 +281,8 @@
         ADD PRIMARY KEY (id),
         ADD UNIQUE KEY user_creation (user,creation),
         ADD KEY thread (thread),
-        ADD INDEX target_message (target_message);
+        ADD INDEX target_message (target_message),
+        ADD INDEX thread_pinned (thread, pinned);
 
       ALTER TABLE notifications
         ADD PRIMARY KEY (id),