diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts
index 1e068eac6a1fc49818f885aced723df985b18a6c..ef3709235c3ed29f15179a03938c5b78c97b3327 100644
--- a/lib/platform/azure/index.ts
+++ b/lib/platform/azure/index.ts
@@ -501,16 +501,59 @@ export async function ensureComment({
   content,
 }: EnsureCommentConfig): Promise<void> {
   logger.debug(`ensureComment(${number}, ${topic}, content)`);
-  const body = `### ${topic}\n\n${sanitize(content)}`;
+  const header = topic ? `### ${topic}\n\n` : '';
+  const body = `${header}${sanitize(content)}`;
   const azureApiGit = await azureApi.gitApi();
-  await azureApiGit.createThread(
-    {
-      comments: [{ content: body, commentType: 1, parentCommentId: 0 }],
-      status: 1,
-    },
-    config.repoId,
-    number
-  );
+
+  const threads = await azureApiGit.getThreads(config.repoId, number);
+  let threadIdFound = null;
+  let commentIdFound = null;
+  let commentNeedsUpdating = false;
+  threads.forEach(thread => {
+    const firstCommentContent = thread.comments[0].content;
+    if (
+      (topic && firstCommentContent.startsWith(header)) ||
+      (!topic && firstCommentContent === body)
+    ) {
+      threadIdFound = thread.id;
+      commentIdFound = thread.comments[0].id;
+      commentNeedsUpdating = firstCommentContent !== body;
+    }
+  });
+
+  if (!threadIdFound) {
+    await azureApiGit.createThread(
+      {
+        comments: [{ content: body, commentType: 1, parentCommentId: 0 }],
+        status: 1,
+      },
+      config.repoId,
+      number
+    );
+    logger.debug(
+      { repository: config.repository, issueNo: number, topic },
+      'Comment added'
+    );
+  } else if (commentNeedsUpdating) {
+    await azureApiGit.updateComment(
+      {
+        content: body,
+      },
+      config.repoId,
+      number,
+      threadIdFound,
+      commentIdFound
+    );
+    logger.debug(
+      { repository: config.repository, issueNo: number, topic },
+      'Comment updated'
+    );
+  } else {
+    logger.debug(
+      { repository: config.repository, issueNo: number, topic },
+      'Comment is already update-to-date'
+    );
+  }
 }
 
 export async function ensureCommentRemoval(
diff --git a/test/platform/azure/__snapshots__/index.spec.ts.snap b/test/platform/azure/__snapshots__/index.spec.ts.snap
index ea8e65413bb2f3ecc71bbf05dabed2db7c0b389d..c7d29e87faef6cd586400271b04a2d3ae134b536 100644
--- a/test/platform/azure/__snapshots__/index.spec.ts.snap
+++ b/test/platform/azure/__snapshots__/index.spec.ts.snap
@@ -42,11 +42,55 @@ Array [
 ]
 `;
 
-exports[`platform/azure ensureComment add comment 1`] = `
+exports[`platform/azure ensureComment adds comment if missing 1`] = `
 Array [
-  Array [],
-  Array [],
-  Array [],
+  Array [
+    Object {
+      "comments": Array [
+        Object {
+          "commentType": 1,
+          "content": "### some-subject
+
+some
+content",
+          "parentCommentId": 0,
+        },
+      ],
+      "status": 1,
+    },
+    "1",
+    42,
+  ],
+]
+`;
+
+exports[`platform/azure ensureComment adds comment if missing 2`] = `Array []`;
+
+exports[`platform/azure ensureComment does nothing if comment exists and is the same 1`] = `Array []`;
+
+exports[`platform/azure ensureComment does nothing if comment exists and is the same 2`] = `Array []`;
+
+exports[`platform/azure ensureComment does nothing if comment exists and is the same when there is no topic 1`] = `Array []`;
+
+exports[`platform/azure ensureComment does nothing if comment exists and is the same when there is no topic 2`] = `Array []`;
+
+exports[`platform/azure ensureComment updates comment if missing 1`] = `Array []`;
+
+exports[`platform/azure ensureComment updates comment if missing 2`] = `
+Array [
+  Array [
+    Object {
+      "content": "### some-subject
+
+some
+new
+content",
+    },
+    "1",
+    42,
+    4,
+    2,
+  ],
 ]
 `;
 
@@ -143,16 +187,25 @@ Object {
 
 exports[`platform/azure updatePr(prNo, title, body) should update the PR 1`] = `
 Array [
-  Array [],
-  Array [],
-  Array [],
+  Array [
+    Object {
+      "description": undefined,
+      "title": "The New Title",
+    },
+    "1",
+    1234,
+  ],
 ]
 `;
 
 exports[`platform/azure updatePr(prNo, title, body) should update the PR without description 1`] = `
 Array [
-  Array [],
-  Array [],
-  Array [],
+  Array [
+    Object {
+      "title": "The New Title - autoclose",
+    },
+    "1",
+    1234,
+  ],
 ]
 `;
diff --git a/test/platform/azure/index.spec.ts b/test/platform/azure/index.spec.ts
index 7a91f30dc3346980db8def7c5171a0304e11768d..5ea357bb3851d88a93bdb899660cfd7b7d4ad68c 100644
--- a/test/platform/azure/index.spec.ts
+++ b/test/platform/azure/index.spec.ts
@@ -642,44 +642,123 @@ describe('platform/azure', () => {
   describe('updatePr(prNo, title, body)', () => {
     it('should update the PR', async () => {
       await initRepo({ repository: 'some/repo' });
+      const updatePullRequest = jest.fn();
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            updatePullRequest: jest.fn(),
+            updatePullRequest,
           } as any)
       );
       await azure.updatePr(1234, 'The New Title', 'Hello world again');
-      expect(azureApi.gitApi.mock.calls).toMatchSnapshot();
+      expect(updatePullRequest.mock.calls).toMatchSnapshot();
     });
 
     it('should update the PR without description', async () => {
       await initRepo({ repository: 'some/repo' });
+      const updatePullRequest = jest.fn();
       azureApi.gitApi.mockImplementationOnce(
         () =>
           ({
-            updatePullRequest: jest.fn(),
+            updatePullRequest,
           } as any)
       );
       await azure.updatePr(1234, 'The New Title - autoclose');
-      expect(azureApi.gitApi.mock.calls).toMatchSnapshot();
+      expect(updatePullRequest.mock.calls).toMatchSnapshot();
     });
   });
 
   describe('ensureComment', () => {
-    it('add comment', async () => {
+    it('adds comment if missing', async () => {
       await initRepo({ repository: 'some/repo' });
-      azureApi.gitApi.mockImplementation(
-        () =>
-          ({
-            createThread: jest.fn(() => [{ id: 123 }]),
-          } as any)
-      );
+      const gitApiMock = {
+        createThread: jest.fn(() => [{ id: 123 }]),
+        getThreads: jest.fn().mockReturnValue([
+          {
+            comments: [{ content: 'end-user comment', id: 1 }],
+            id: 2,
+          },
+        ]),
+        updateComment: jest.fn(() => ({ id: 123 })),
+      };
+      azureApi.gitApi.mockImplementation(() => gitApiMock as any);
       await azure.ensureComment({
         number: 42,
         topic: 'some-subject',
         content: 'some\ncontent',
       });
-      expect(azureApi.gitApi.mock.calls).toMatchSnapshot();
+      expect(gitApiMock.createThread.mock.calls).toMatchSnapshot();
+      expect(gitApiMock.updateComment.mock.calls).toMatchSnapshot();
+    });
+    it('updates comment if missing', async () => {
+      await initRepo({ repository: 'some/repo' });
+      const gitApiMock = {
+        createThread: jest.fn(() => [{ id: 123 }]),
+        getThreads: jest.fn().mockReturnValue([
+          {
+            comments: [{ content: 'end-user comment', id: 1 }],
+            id: 3,
+          },
+          {
+            comments: [{ content: '### some-subject\n\nsome\ncontent', id: 2 }],
+            id: 4,
+          },
+        ]),
+        updateComment: jest.fn(() => ({ id: 123 })),
+      };
+      azureApi.gitApi.mockImplementation(() => gitApiMock as any);
+      await azure.ensureComment({
+        number: 42,
+        topic: 'some-subject',
+        content: 'some\nnew\ncontent',
+      });
+      expect(gitApiMock.createThread.mock.calls).toMatchSnapshot();
+      expect(gitApiMock.updateComment.mock.calls).toMatchSnapshot();
+    });
+    it('does nothing if comment exists and is the same', async () => {
+      await initRepo({ repository: 'some/repo' });
+      const gitApiMock = {
+        createThread: jest.fn(() => [{ id: 123 }]),
+        getThreads: jest.fn().mockReturnValue([
+          {
+            comments: [{ content: 'end-user comment', id: 1 }],
+            id: 3,
+          },
+          {
+            comments: [{ content: '### some-subject\n\nsome\ncontent', id: 2 }],
+            id: 4,
+          },
+        ]),
+        updateComment: jest.fn(() => ({ id: 123 })),
+      };
+      azureApi.gitApi.mockImplementation(() => gitApiMock as any);
+      await azure.ensureComment({
+        number: 42,
+        topic: 'some-subject',
+        content: 'some\ncontent',
+      });
+      expect(gitApiMock.createThread.mock.calls).toMatchSnapshot();
+      expect(gitApiMock.updateComment.mock.calls).toMatchSnapshot();
+    });
+    it('does nothing if comment exists and is the same when there is no topic', async () => {
+      await initRepo({ repository: 'some/repo' });
+      const gitApiMock = {
+        createThread: jest.fn(() => [{ id: 123 }]),
+        getThreads: jest.fn().mockReturnValue([
+          {
+            comments: [{ content: 'some\ncontent', id: 2 }],
+            id: 4,
+          },
+        ]),
+        updateComment: jest.fn(() => ({ id: 123 })),
+      };
+      azureApi.gitApi.mockImplementation(() => gitApiMock as any);
+      await azure.ensureComment({
+        number: 42,
+        topic: null,
+        content: 'some\ncontent',
+      });
+      expect(gitApiMock.createThread.mock.calls).toMatchSnapshot();
+      expect(gitApiMock.updateComment.mock.calls).toMatchSnapshot();
     });
   });
 
@@ -728,6 +807,7 @@ describe('platform/azure', () => {
         () =>
           ({
             createThread: jest.fn(() => [{ id: 123 }]),
+            getThreads: jest.fn(() => []),
           } as any)
       );
       await azure.addAssignees(123, ['test@bonjour.fr']);