diff --git a/lib/shared/messages/delete-message-spec.js b/lib/shared/messages/delete-message-spec.js
--- a/lib/shared/messages/delete-message-spec.js
+++ b/lib/shared/messages/delete-message-spec.js
@@ -2,7 +2,8 @@
 
 import invariant from 'invariant';
 
-import type { MessageSpec } from './message-spec.js';
+import type { MessageSpec, MessageTitleParam } from './message-spec.js';
+import type { PlatformDetails } from '../../types/device-types.js';
 import {
   assertMessageType,
   messageTypes,
@@ -14,13 +15,43 @@
   RawDeleteMessageInfo,
 } from '../../types/messages/delete.js';
 import { rawDeleteMessageInfoValidator } from '../../types/messages/delete.js';
+import type { RawUnsupportedMessageInfo } from '../../types/messages/unsupported.js';
 import type { RelativeUserInfo } from '../../types/user-types.js';
+import { ET } from '../../utils/entity-text.js';
+import { FUTURE_CODE_VERSION, hasMinCodeVersion } from '../version-utils.js';
 
 export const deleteMessageSpec: MessageSpec<
   DeleteMessageData,
   RawDeleteMessageInfo,
   DeleteMessageInfo,
 > = Object.freeze({
+  messageContentForClientDB(data: RawDeleteMessageInfo): string {
+    return JSON.stringify({
+      targetMessageID: data.targetMessageID,
+    });
+  },
+
+  messageTitle({ messageInfo }: MessageTitleParam<DeleteMessageInfo>) {
+    const creator = ET.user({ userInfo: messageInfo.creator });
+    return ET`${creator} deleted a message`;
+  },
+
+  rawMessageInfoFromServerDBRow(row: Object): RawDeleteMessageInfo {
+    invariant(
+      row.targetMessageID !== null && row.targetMessageID !== undefined,
+      'targetMessageID should be set',
+    );
+
+    return {
+      type: messageTypes.DELETE_MESSAGE,
+      id: row.id.toString(),
+      threadID: row.threadID.toString(),
+      time: row.time,
+      creatorID: row.creatorID.toString(),
+      targetMessageID: row.targetMessageID.toString(),
+    };
+  },
+
   rawMessageInfoFromClientDB(
     clientDBMessageInfo: ClientDBMessageInfo,
   ): RawDeleteMessageInfo {
@@ -60,7 +91,49 @@
     };
   },
 
+  rawMessageInfoFromMessageData(
+    messageData: DeleteMessageData,
+    id: ?string,
+  ): RawDeleteMessageInfo {
+    invariant(id, 'RawDeleteMessageInfo needs id');
+    return { ...messageData, id };
+  },
+
+  shimUnsupportedMessageInfo(
+    rawMessageInfo: RawDeleteMessageInfo,
+    platformDetails: ?PlatformDetails,
+  ): RawDeleteMessageInfo | RawUnsupportedMessageInfo {
+    if (
+      hasMinCodeVersion(platformDetails, {
+        native: FUTURE_CODE_VERSION,
+        web: FUTURE_CODE_VERSION,
+      })
+    ) {
+      return rawMessageInfo;
+    }
+    const { id } = rawMessageInfo;
+    invariant(id !== null && id !== undefined, 'id should be set on server');
+
+    return {
+      type: messageTypes.UNSUPPORTED,
+      id,
+      threadID: rawMessageInfo.threadID,
+      creatorID: rawMessageInfo.creatorID,
+      time: rawMessageInfo.time,
+      robotext: 'deleted a message',
+      unsupportedMessageInfo: rawMessageInfo,
+    };
+  },
+
+  unshimMessageInfo(unwrapped: RawDeleteMessageInfo): RawDeleteMessageInfo {
+    return unwrapped;
+  },
+
   canBeSidebarSource: false,
+
   canBePinned: false,
+
+  canBeRenderedIndependently: false,
+
   validator: rawDeleteMessageInfoValidator,
 });