diff --git a/packages/server/database/rethinkDriver.ts b/packages/server/database/rethinkDriver.ts
index e52e2dd4ea8..50f42952ff7 100644
--- a/packages/server/database/rethinkDriver.ts
+++ b/packages/server/database/rethinkDriver.ts
@@ -197,7 +197,7 @@ export type RethinkSchema = {
   }
   TemplateDimension: {
     type: TemplateDimension
-    index: 'teamId' | 'templateId'
+    index: 'teamId' | 'templateId' | 'scaleId'
   }
   TemplateScale: {
     type: TemplateScale
diff --git a/packages/server/graphql/mutations/addPokerTemplateDimension.ts b/packages/server/graphql/mutations/addPokerTemplateDimension.ts
index 676392cd947..ff1d5a1e2ef 100644
--- a/packages/server/graphql/mutations/addPokerTemplateDimension.ts
+++ b/packages/server/graphql/mutations/addPokerTemplateDimension.ts
@@ -4,6 +4,7 @@ import dndNoise from 'parabol-client/utils/dndNoise'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
 import TemplateDimension from '../../database/types/TemplateDimension'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const addPokerTemplateDimension = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
     const template = await dataLoader.get('meetingTemplates').load(templateId)
@@ -73,7 +75,14 @@ const addPokerTemplateDimension = {
       templateId
     })
 
-    await r.table('TemplateDimension').insert(newDimension).run()
+    await Promise.all([
+      r.table('TemplateDimension').insert(newDimension).run(),
+      pg
+        .updateTable('MeetingTemplate')
+        .set({updatedAt: new Date()})
+        .where('id', '=', templateId)
+        .execute()
+    ])
 
     const dimensionId = newDimension.id
     const data = {dimensionId}
diff --git a/packages/server/graphql/mutations/addPokerTemplateScaleValue.ts b/packages/server/graphql/mutations/addPokerTemplateScaleValue.ts
index 8e20ccb812b..3470e9418dc 100644
--- a/packages/server/graphql/mutations/addPokerTemplateScaleValue.ts
+++ b/packages/server/graphql/mutations/addPokerTemplateScaleValue.ts
@@ -3,6 +3,7 @@ import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
 import TemplateScale from '../../database/types/TemplateScale'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -32,6 +33,7 @@ const addPokerTemplateScaleValue = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -84,6 +86,18 @@ const addPokerTemplateScaleValue = {
       })
     }
 
+    // mark all templates using this scale as updated
+    const updatedDimensions = await r
+      .table('TemplateDimension')
+      .getAll(scaleId, {index: 'scaleId'})
+      .run()
+    const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
+
     const data = {scaleId}
     publish(
       SubscriptionChannel.TEAM,
diff --git a/packages/server/graphql/mutations/addReflectTemplatePrompt.ts b/packages/server/graphql/mutations/addReflectTemplatePrompt.ts
index 7f8b4c3c9ad..e0867254b79 100644
--- a/packages/server/graphql/mutations/addReflectTemplatePrompt.ts
+++ b/packages/server/graphql/mutations/addReflectTemplatePrompt.ts
@@ -5,6 +5,7 @@ import palettePickerOptions from '../../../client/styles/palettePickerOptions'
 import {PALETTE} from '../../../client/styles/paletteV3'
 import getRethink from '../../database/rethinkDriver'
 import RetrospectivePrompt from '../../database/types/RetrospectivePrompt'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -25,6 +26,7 @@ const addReflectTemplatePrompt = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
     const template = await dataLoader.get('meetingTemplates').load(templateId)
@@ -69,7 +71,14 @@ const addReflectTemplatePrompt = {
       removedAt: null
     })
 
-    await r.table('ReflectPrompt').insert(reflectPrompt).run()
+    await Promise.all([
+      await r.table('ReflectPrompt').insert(reflectPrompt).run(),
+      pg
+        .updateTable('MeetingTemplate')
+        .set({updatedAt: new Date()})
+        .where('id', '=', templateId)
+        .execute()
+    ])
 
     const promptId = reflectPrompt.id
     const data = {promptId}
diff --git a/packages/server/graphql/mutations/movePokerTemplateDimension.ts b/packages/server/graphql/mutations/movePokerTemplateDimension.ts
index 7d5523cbcd4..3f037e6e223 100644
--- a/packages/server/graphql/mutations/movePokerTemplateDimension.ts
+++ b/packages/server/graphql/mutations/movePokerTemplateDimension.ts
@@ -1,6 +1,7 @@
 import {GraphQLFloat, GraphQLID, GraphQLNonNull} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const movePokerTemplateDimension = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -39,16 +41,20 @@ const movePokerTemplateDimension = {
     }
 
     // RESOLUTION
-    await r
-      .table('TemplateDimension')
-      .get(dimensionId)
-      .update({
-        sortOrder,
-        updatedAt: now
-      })
-      .run()
+    const {teamId, templateId} = dimension
+
+    await Promise.all([
+      r
+        .table('TemplateDimension')
+        .get(dimensionId)
+        .update({
+          sortOrder,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
-    const {teamId} = dimension
     const data = {dimensionId}
     publish(SubscriptionChannel.TEAM, teamId, 'MovePokerTemplateDimensionPayload', data, subOptions)
     return data
diff --git a/packages/server/graphql/mutations/movePokerTemplateScaleValue.ts b/packages/server/graphql/mutations/movePokerTemplateScaleValue.ts
index 5fd63247107..6da4d67829d 100644
--- a/packages/server/graphql/mutations/movePokerTemplateScaleValue.ts
+++ b/packages/server/graphql/mutations/movePokerTemplateScaleValue.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RValue} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -30,6 +31,7 @@ const movePokerTemplateScaleValue = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) => {
     const r = await getRethink()
+    const pg = getKysely()
     const viewerId = getUserId(authToken)
     const now = new Date()
     const operationId = dataLoader.share()
@@ -66,6 +68,17 @@ const movePokerTemplateScaleValue = {
         updatedAt: now
       }))
       .run()
+    // mark all templates using this scale as updated
+    const updatedDimensions = await r
+      .table('TemplateDimension')
+      .getAll(scaleId, {index: 'scaleId'})
+      .run()
+    const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
 
     const data = {scaleId}
     publish(
diff --git a/packages/server/graphql/mutations/moveReflectTemplatePrompt.ts b/packages/server/graphql/mutations/moveReflectTemplatePrompt.ts
index 21ed63083cd..2a02c13f9d7 100644
--- a/packages/server/graphql/mutations/moveReflectTemplatePrompt.ts
+++ b/packages/server/graphql/mutations/moveReflectTemplatePrompt.ts
@@ -1,6 +1,7 @@
 import {GraphQLFloat, GraphQLID, GraphQLNonNull} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const moveReflectTemplate = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -39,16 +41,20 @@ const moveReflectTemplate = {
     }
 
     // RESOLUTION
-    await r
-      .table('ReflectPrompt')
-      .get(promptId)
-      .update({
-        sortOrder,
-        updatedAt: now
-      })
-      .run()
+    const {teamId, templateId} = prompt
+
+    await Promise.all([
+      r
+        .table('ReflectPrompt')
+        .get(promptId)
+        .update({
+          sortOrder,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
-    const {teamId} = prompt
     const data = {promptId}
     publish(SubscriptionChannel.TEAM, teamId, 'MoveReflectTemplatePromptPayload', data, subOptions)
     return data
diff --git a/packages/server/graphql/mutations/reflectTemplatePromptUpdateDescription.ts b/packages/server/graphql/mutations/reflectTemplatePromptUpdateDescription.ts
index 23c00074fbd..73254ea5522 100644
--- a/packages/server/graphql/mutations/reflectTemplatePromptUpdateDescription.ts
+++ b/packages/server/graphql/mutations/reflectTemplatePromptUpdateDescription.ts
@@ -1,6 +1,7 @@
 import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const reflectTemplatePromptUpdateDescription = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -39,18 +41,21 @@ const reflectTemplatePromptUpdateDescription = {
     }
 
     // VALIDATION
-    const {teamId} = prompt
+    const {teamId, templateId} = prompt
     const normalizedDescription = description.trim().slice(0, 256) || ''
 
     // RESOLUTION
-    await r
-      .table('ReflectPrompt')
-      .get(promptId)
-      .update({
-        description: normalizedDescription,
-        updatedAt: now
-      })
-      .run()
+    await Promise.all([
+      r
+        .table('ReflectPrompt')
+        .get(promptId)
+        .update({
+          description: normalizedDescription,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {promptId}
     publish(
diff --git a/packages/server/graphql/mutations/reflectTemplatePromptUpdateGroupColor.ts b/packages/server/graphql/mutations/reflectTemplatePromptUpdateGroupColor.ts
index 1b1b381a590..c7c397d1a99 100644
--- a/packages/server/graphql/mutations/reflectTemplatePromptUpdateGroupColor.ts
+++ b/packages/server/graphql/mutations/reflectTemplatePromptUpdateGroupColor.ts
@@ -1,6 +1,7 @@
 import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const reflectTemplatePromptUpdateGroupColor = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -40,17 +42,20 @@ const reflectTemplatePromptUpdateGroupColor = {
     }
 
     // VALIDATION
-    const {teamId} = prompt
+    const {teamId, templateId} = prompt
 
     // RESOLUTION
-    await r
-      .table('ReflectPrompt')
-      .get(promptId)
-      .update({
-        groupColor,
-        updatedAt: now
-      })
-      .run()
+    await Promise.all([
+      r
+        .table('ReflectPrompt')
+        .get(promptId)
+        .update({
+          groupColor,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {promptId}
     publish(
diff --git a/packages/server/graphql/mutations/removePokerTemplateDimension.ts b/packages/server/graphql/mutations/removePokerTemplateDimension.ts
index 02393715f2e..308ba0850b0 100644
--- a/packages/server/graphql/mutations/removePokerTemplateDimension.ts
+++ b/packages/server/graphql/mutations/removePokerTemplateDimension.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLNonNull} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -22,6 +23,7 @@ const removePokerTemplateDimension = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -52,7 +54,10 @@ const removePokerTemplateDimension = {
     }
 
     // RESOLUTION
-    await r.table('TemplateDimension').get(dimensionId).update({removedAt: now}).run()
+    await Promise.all([
+      r.table('TemplateDimension').get(dimensionId).update({removedAt: now}).run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {dimensionId, templateId}
     publish(
diff --git a/packages/server/graphql/mutations/removePokerTemplateScale.ts b/packages/server/graphql/mutations/removePokerTemplateScale.ts
index 59bc5460c65..b56255592f4 100644
--- a/packages/server/graphql/mutations/removePokerTemplateScale.ts
+++ b/packages/server/graphql/mutations/removePokerTemplateScale.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLNonNull} from 'graphql'
 import {SprintPokerDefaults, SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -22,6 +23,7 @@ const removePokerTemplateScale = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -56,6 +58,13 @@ const removePokerTemplateScale = {
       )('changes')('new_val')
       .default([])
       .run()
+    // mark templates as updated
+    const updatedTemplateIds = dimensions.map(({templateId}: any) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
 
     const data = {scaleId, dimensions}
     publish(SubscriptionChannel.TEAM, teamId, 'RemovePokerTemplateScalePayload', data, subOptions)
diff --git a/packages/server/graphql/mutations/removePokerTemplateScaleValue.ts b/packages/server/graphql/mutations/removePokerTemplateScaleValue.ts
index 5ce74911a47..9caecbfeab5 100644
--- a/packages/server/graphql/mutations/removePokerTemplateScaleValue.ts
+++ b/packages/server/graphql/mutations/removePokerTemplateScaleValue.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RValue} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -25,6 +26,7 @@ const removePokerTemplateScaleValue = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -58,6 +60,18 @@ const removePokerTemplateScaleValue = {
       }))
       .run()
 
+    // mark all templates using this scale as updated
+    const updatedDimensions = await r
+      .table('TemplateDimension')
+      .getAll(scaleId, {index: 'scaleId'})
+      .run()
+    const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
+
     const data = {scaleId}
     publish(
       SubscriptionChannel.TEAM,
diff --git a/packages/server/graphql/mutations/removeReflectTemplatePrompt.ts b/packages/server/graphql/mutations/removeReflectTemplatePrompt.ts
index 6737181ccc2..b0f2f1eebaf 100644
--- a/packages/server/graphql/mutations/removeReflectTemplatePrompt.ts
+++ b/packages/server/graphql/mutations/removeReflectTemplatePrompt.ts
@@ -1,6 +1,7 @@
 import {GraphQLID, GraphQLNonNull} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -21,6 +22,7 @@ const removeReflectTemplatePrompt = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -53,14 +55,17 @@ const removeReflectTemplatePrompt = {
     }
 
     // RESOLUTION
-    await r
-      .table('ReflectPrompt')
-      .get(promptId)
-      .update({
-        removedAt: now,
-        updatedAt: now
-      })
-      .run()
+    await Promise.all([
+      r
+        .table('ReflectPrompt')
+        .get(promptId)
+        .update({
+          removedAt: now,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {promptId, templateId}
     publish(
diff --git a/packages/server/graphql/mutations/renamePokerTemplateDimension.ts b/packages/server/graphql/mutations/renamePokerTemplateDimension.ts
index 49665377f50..21b76b33471 100644
--- a/packages/server/graphql/mutations/renamePokerTemplateDimension.ts
+++ b/packages/server/graphql/mutations/renamePokerTemplateDimension.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel, Threshold} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -25,6 +26,7 @@ const renamePokerTemplateDimension = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -55,14 +57,17 @@ const renamePokerTemplateDimension = {
     }
 
     // RESOLUTION
-    await r
-      .table('TemplateDimension')
-      .get(dimensionId)
-      .update({
-        name: normalizedName,
-        updatedAt: now
-      })
-      .run()
+    await Promise.all([
+      r
+        .table('TemplateDimension')
+        .get(dimensionId)
+        .update({
+          name: normalizedName,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {dimensionId}
     publish(
diff --git a/packages/server/graphql/mutations/renamePokerTemplateScale.ts b/packages/server/graphql/mutations/renamePokerTemplateScale.ts
index 4aca5cc53f5..f9b42c50778 100644
--- a/packages/server/graphql/mutations/renamePokerTemplateScale.ts
+++ b/packages/server/graphql/mutations/renamePokerTemplateScale.ts
@@ -2,6 +2,7 @@ import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
 import {RDatum} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -25,6 +26,7 @@ const renamePokerTemplateScale = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -63,6 +65,18 @@ const renamePokerTemplateScale = {
       })
       .run()
 
+    // mark all templates using this scale as updated
+    const updatedDimensions = await r
+      .table('TemplateDimension')
+      .getAll(scaleId, {index: 'scaleId'})
+      .run()
+    const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
+
     const data = {scaleId}
     publish(SubscriptionChannel.TEAM, teamId, 'RenamePokerTemplateScalePayload', data, subOptions)
     return data
diff --git a/packages/server/graphql/mutations/renameReflectTemplatePrompt.ts b/packages/server/graphql/mutations/renameReflectTemplatePrompt.ts
index f1c4f0ee736..b1a74470ebc 100644
--- a/packages/server/graphql/mutations/renameReflectTemplatePrompt.ts
+++ b/packages/server/graphql/mutations/renameReflectTemplatePrompt.ts
@@ -1,6 +1,7 @@
 import {GraphQLID, GraphQLNonNull, GraphQLString} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const renameReflectTemplatePrompt = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -56,14 +58,17 @@ const renameReflectTemplatePrompt = {
     }
 
     // RESOLUTION
-    await r
-      .table('ReflectPrompt')
-      .get(promptId)
-      .update({
-        question: normalizedQuestion,
-        updatedAt: now
-      })
-      .run()
+    await Promise.all([
+      r
+        .table('ReflectPrompt')
+        .get(promptId)
+        .update({
+          question: normalizedQuestion,
+          updatedAt: now
+        })
+        .run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {promptId}
     publish(
diff --git a/packages/server/graphql/mutations/updatePokerTemplateDimensionScale.ts b/packages/server/graphql/mutations/updatePokerTemplateDimensionScale.ts
index ea35b3ec46a..479eba4abfb 100644
--- a/packages/server/graphql/mutations/updatePokerTemplateDimensionScale.ts
+++ b/packages/server/graphql/mutations/updatePokerTemplateDimensionScale.ts
@@ -1,6 +1,7 @@
 import {GraphQLID, GraphQLNonNull} from 'graphql'
 import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import getRethink from '../../database/rethinkDriver'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -24,6 +25,7 @@ const updatePokerTemplateDimensionScale = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -45,7 +47,11 @@ const updatePokerTemplateDimensionScale = {
       return standardError(new Error('Scale not found'), {userId: viewerId})
     }
 
-    await r.table('TemplateDimension').get(dimensionId).update({scaleId, updatedAt: now}).run()
+    const {templateId} = dimension
+    await Promise.all([
+      r.table('TemplateDimension').get(dimensionId).update({scaleId, updatedAt: now}).run(),
+      pg.updateTable('MeetingTemplate').set({updatedAt: now}).where('id', '=', templateId).execute()
+    ])
 
     const data = {dimensionId}
     publish(
diff --git a/packages/server/graphql/mutations/updatePokerTemplateScaleValue.ts b/packages/server/graphql/mutations/updatePokerTemplateScaleValue.ts
index 546d30c348a..64ce07cab26 100644
--- a/packages/server/graphql/mutations/updatePokerTemplateScaleValue.ts
+++ b/packages/server/graphql/mutations/updatePokerTemplateScaleValue.ts
@@ -3,6 +3,7 @@ import {SubscriptionChannel} from 'parabol-client/types/constEnums'
 import isSpecialPokerLabel from 'parabol-client/utils/isSpecialPokerLabel'
 import getRethink from '../../database/rethinkDriver'
 import {RValue} from '../../database/stricterR'
+import getKysely from '../../postgres/getKysely'
 import {getUserId, isTeamMember} from '../../utils/authorization'
 import publish from '../../utils/publish'
 import standardError from '../../utils/standardError'
@@ -43,6 +44,7 @@ const updatePokerTemplateScaleValue = {
     {authToken, dataLoader, socketId: mutatorId}: GQLContext
   ) {
     const r = await getRethink()
+    const pg = getKysely()
     const now = new Date()
     const operationId = dataLoader.share()
     const subOptions = {operationId, mutatorId}
@@ -107,6 +109,18 @@ const updatePokerTemplateScaleValue = {
       })
     }
 
+    // mark all templates using this scale as updated
+    const updatedDimensions = await r
+      .table('TemplateDimension')
+      .getAll(scaleId, {index: 'scaleId'})
+      .run()
+    const updatedTemplateIds = updatedDimensions.map(({templateId}) => templateId)
+    await pg
+      .updateTable('MeetingTemplate')
+      .set({updatedAt: now})
+      .where('id', 'in', updatedTemplateIds)
+      .execute()
+
     const data = {scaleId}
     publish(
       SubscriptionChannel.TEAM,
diff --git a/packages/server/postgres/migrations/1717685812676_addPokerTemplateScaleDimensionScaleIdIndex.ts b/packages/server/postgres/migrations/1717685812676_addPokerTemplateScaleDimensionScaleIdIndex.ts
new file mode 100644
index 00000000000..384ec9f1c3f
--- /dev/null
+++ b/packages/server/postgres/migrations/1717685812676_addPokerTemplateScaleDimensionScaleIdIndex.ts
@@ -0,0 +1,21 @@
+import {r} from 'rethinkdb-ts'
+import connectRethinkDB from '../../database/connectRethinkDB'
+
+export async function up() {
+  await connectRethinkDB()
+  try {
+    await r.table('TemplateDimension').indexCreate('scaleId').run()
+    await r.table('TemplateDimension').indexWait().run()
+  } catch {
+    // index already exists
+  }
+}
+
+export async function down() {
+  await connectRethinkDB()
+  try {
+    await r.table('TemplateDimension').indexDrop('scaleId').run()
+  } catch {
+    // index already dropped
+  }
+}