diff --git a/communication/provider/matrix/classes/communication_feature.php b/communication/provider/matrix/classes/communication_feature.php
index f5254a0a49e..7c51eb22588 100644
--- a/communication/provider/matrix/classes/communication_feature.php
+++ b/communication/provider/matrix/classes/communication_feature.php
@@ -304,21 +304,26 @@ class communication_feature implements
      * Update the room avatar when an instance image is added or updated.
      */
     public function update_room_avatar(): void {
-        $instanceimage = $this->communication->get_avatar();
-        $contenturi = null;
 
-        // If avatar is set for the instance, update in matrix.
-        if (!empty($instanceimage)) {
-            // First upload the content.
-            $contenturi = $this->eventmanager->upload_matrix_content($instanceimage->get_content());
+        // Check if we have an avatar that needs to be synced.
+        if (!$this->communication->is_avatar_synced()) {
+
+            $instanceimage = $this->communication->get_avatar();
+            $contenturi = null;
+
+            // If avatar is set for the instance, upload to Matrix. Otherwise, leave null for unsetting.
+            if (!empty($instanceimage)) {
+                $contenturi = $this->eventmanager->upload_matrix_content($instanceimage->get_content());
+            }
+
+            $response = $this->eventmanager->request(['url' => $contenturi], [], false)->put(
+                $this->eventmanager->get_update_avatar_endpoint());
+
+            // Indicate the avatar has been synced if it was successfully set with Matrix.
+            if ($response->getReasonPhrase() === 'OK') {
+                $this->communication->set_avatar_synced_flag(true);
+            }
         }
-
-        // Now update the room avatar.
-        $json = [
-            'url' => $contenturi,
-        ];
-
-        $this->eventmanager->request($json, [], false)->put($this->eventmanager->get_update_avatar_endpoint());
     }
 
     public function get_chat_room_url(): ?string {
diff --git a/communication/provider/matrix/tests/matrix_communication_test.php b/communication/provider/matrix/tests/matrix_communication_test.php
index d2e3e699565..b59f9e4376a 100644
--- a/communication/provider/matrix/tests/matrix_communication_test.php
+++ b/communication/provider/matrix/tests/matrix_communication_test.php
@@ -81,6 +81,7 @@ class matrix_communication_test extends \advanced_testcase {
      * @covers \core_communication\api::update_room
      * @covers \core_communication\task\update_room_task::execute
      * @covers \core_communication\task\update_room_task::queue
+     * @covers \core_communication\processor::is_avatar_synced
      */
     public function test_update_course_with_matrix_provider(): void {
         global $CFG;
@@ -101,6 +102,15 @@ class matrix_communication_test extends \advanced_testcase {
         );
         $communication->update_room($selectedcommunication, $communicationroomname, $avatarurl);
 
+        $communicationprocessor = processor::load_by_instance(
+            'core_course',
+            'coursecommunication',
+            $course->id
+        );
+
+        // Pending avatar update should indicate avatar is not in sync.
+        $this->assertFalse($communicationprocessor->is_avatar_synced());
+
         // Run the task.
         $this->runAdhocTasks('\core_communication\task\update_room_task');
 
@@ -110,6 +120,9 @@ class matrix_communication_test extends \advanced_testcase {
             $course->id
         );
 
+        // Check that the avatar is now synced with Matrix again.
+        $this->assertTrue($communicationprocessor->is_avatar_synced());
+
         // Initialize the matrix room object.
         $matrixrooms = new matrix_rooms($communicationprocessor->get_id());