diff --git a/addons/board/static/src/board_controller.js b/addons/board/static/src/board_controller.js
index 367038267e116d526b27881c83feee912cb56965..5f7304ce25a338c40857cfbc3cfaa01c69abaf8a 100644
--- a/addons/board/static/src/board_controller.js
+++ b/addons/board/static/src/board_controller.js
@@ -10,7 +10,7 @@ import { useSortable } from "@web/core/utils/sortable";
 import { standardViewProps } from "@web/views/standard_view_props";
 import { BoardAction } from "./board_action";
 
-const { Component, useState, useRef } = owl;
+const { blockDom, Component, useState, useRef } = owl;
 
 export class BoardController extends Component {
     setup() {
@@ -102,9 +102,16 @@ export class BoardController extends Component {
     }
 
     saveBoard() {
+        const templateFn = renderToString.app.getTemplate("board.arch");
+        const bdom = templateFn(this.board, {});
+        const root = document.createElement("rendertostring");
+        blockDom.mount(bdom, root);
+        const result = xmlSerializer.serializeToString(root);
+        const arch = result.slice(result.indexOf('<', 1), result.indexOf('</rendertostring>'));
+
         this.rpc("/web/view/edit_custom", {
             custom_id: this.board.customViewId,
-            arch: renderToString("board.arch", this.board),
+            arch,
         });
         this.env.bus.trigger("CLEAR-CACHES");
     }
@@ -116,3 +123,5 @@ BoardController.props = {
     ...standardViewProps,
     board: Object,
 };
+
+const xmlSerializer = new XMLSerializer();
diff --git a/addons/board/static/src/board_view.js b/addons/board/static/src/board_view.js
index 431978a99b93f763fee864c620440a027fd24044..8cfef9aacfce7bf6116eb38144911ddccabc2317 100644
--- a/addons/board/static/src/board_view.js
+++ b/addons/board/static/src/board_view.js
@@ -45,10 +45,14 @@ export class BoardArchParser extends XMLParser {
                         isFolded,
                     };
                     if (node.hasAttribute("domain")) {
-                        action.domain = new Domain(_.unescape(node.getAttribute("domain"))).toList();
+                        let domain = node.getAttribute("domain");
+                        // Since bfadb8e491fe2acda63a79f9577eaaec8a1c8d9c some databases might have
+                        // double-encoded domains in the db, so we need to unescape them before use.
+                        // TODO: remove unescape in saas-16.3
+                        domain = _.unescape(domain);
+                        action.domain = new Domain(domain).toList();
                         // so it can be serialized when reexporting board xml
-                        // we unescape before re-escaping, to avoid double escaping due to subsequent layout change
-                        action.domain.toString = () => _.escape(_.unescape(node.getAttribute("domain")));
+                        action.domain.toString = () => node.getAttribute("domain");
                     }
                     archInfo.columns[currentIndex].actions.push(action);
                     break;