diff --git a/lib/automake.mk b/lib/automake.mk
index 3a2da1fe4..7ae5528fb 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -41,6 +41,8 @@ lib_libovn_la_SOURCES = \
 	lib/static-mac-binding-index.c \
 	lib/static-mac-binding-index.h \
 	lib/stopwatch-names.h \
+	lib/template-var.c \
+	lib/template-var.h \
 	lib/vif-plug-provider.h \
 	lib/vif-plug-provider.c \
 	lib/vif-plug-providers/dummy/vif-plug-dummy.c
diff --git a/lib/template-var.c b/lib/template-var.c
new file mode 100644
index 000000000..1a6d4dfbb
--- /dev/null
+++ b/lib/template-var.c
@@ -0,0 +1,41 @@
+/* Copyright (c) 2022 Red Hat, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "lib/template-var.h"
+
+struct ovsdb_idl_index *
+sbrec_template_var_by_name_chassis_index_create(struct ovsdb_idl *idl)
+{
+    return ovsdb_idl_index_create2(idl, &sbrec_template_var_col_name,
+                                   &sbrec_template_var_col_chassis);
+}
+
+const struct sbrec_template_var *
+sb_template_var_lookup_by_name_chassis(
+    struct ovsdb_idl_index *sbrec_template_var_by_name_chassis,
+    const char *name, const char *chassis)
+{
+    struct sbrec_template_var *target =
+        sbrec_template_var_index_init_row(sbrec_template_var_by_name_chassis);
+    sbrec_template_var_index_set_name(target, name);
+    sbrec_template_var_index_set_chassis(target, chassis);
+
+    struct sbrec_template_var *retval =
+        sbrec_template_var_index_find(sbrec_template_var_by_name_chassis,
+                                      target);
+    sbrec_template_var_index_destroy_row(target);
+    return retval;
+}
diff --git a/lib/template-var.h b/lib/template-var.h
new file mode 100644
index 000000000..33351055f
--- /dev/null
+++ b/lib/template-var.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2022, Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OVN_TEMPLATE_VAR_H
+#define OVN_TEMPLATE_VAR_H 1
+
+#include "ovn-sb-idl.h"
+
+struct ovsdb_idl_index *sbrec_template_var_by_name_chassis_index_create(
+    struct ovsdb_idl *idl);
+
+const struct sbrec_template_var *sb_template_var_lookup_by_name_chassis(
+    struct ovsdb_idl_index *sbrec_template_var_by_name_chassis,
+    const char *name, const char *chassis);
+
+#endif /* lib/template-var.h */
diff --git a/northd/en-northd.c b/northd/en-northd.c
index 4907a1ff2..ec89ec002 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -59,6 +59,10 @@ void en_northd_run(struct engine_node *node, void *data)
         engine_ovsdb_node_get_index(
             engine_get_input("SB_static_mac_binding", node),
             "sbrec_static_mac_binding_by_lport_ip");
+    input_data.sbrec_template_var_by_name_chassis =
+        engine_ovsdb_node_get_index(
+            engine_get_input("SB_template_var", node),
+            "sbrec_template_var_by_name_chassis");
 
     input_data.nbrec_nb_global_table =
         EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
@@ -78,6 +82,8 @@ void en_northd_run(struct engine_node *node, void *data)
         EN_OVSDB_GET(engine_get_input("NB_acl", node));
     input_data.nbrec_static_mac_binding_table =
         EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node));
+    input_data.nbrec_template_var_table =
+        EN_OVSDB_GET(engine_get_input("NB_template_var", node));
 
     input_data.sbrec_sb_global_table =
         EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 43093cb5a..feb0ffe04 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -24,6 +24,7 @@
 #include "lib/inc-proc-eng.h"
 #include "lib/ovn-nb-idl.h"
 #include "lib/ovn-sb-idl.h"
+#include "lib/template-var.h"
 #include "mcast-group-index.h"
 #include "openvswitch/poll-loop.h"
 #include "openvswitch/vlog.h"
@@ -62,7 +63,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
     NB_NODE(ha_chassis_group, "ha_chassis_group") \
     NB_NODE(ha_chassis, "ha_chassis") \
     NB_NODE(bfd, "bfd") \
-    NB_NODE(static_mac_binding, "static_mac_binding")
+    NB_NODE(static_mac_binding, "static_mac_binding") \
+    NB_NODE(template_var, "template_var")
 
     enum nb_engine_node {
 #define NB_NODE(NAME, NAME_STR) NB_##NAME,
@@ -112,7 +114,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd);
     SB_NODE(load_balancer, "load_balancer") \
     SB_NODE(bfd, "bfd") \
     SB_NODE(fdb, "fdb") \
-    SB_NODE(static_mac_binding, "static_mac_binding")
+    SB_NODE(static_mac_binding, "static_mac_binding") \
+    SB_NODE(template_var, "template_var")
 
 enum sb_engine_node {
 #define SB_NODE(NAME, NAME_STR) SB_##NAME,
@@ -182,6 +185,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_northd, &en_nb_ha_chassis_group, NULL);
     engine_add_input(&en_northd, &en_nb_ha_chassis, NULL);
     engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL);
+    engine_add_input(&en_northd, &en_nb_template_var, NULL);
 
     engine_add_input(&en_northd, &en_sb_sb_global, NULL);
     engine_add_input(&en_northd, &en_sb_chassis, NULL);
@@ -211,6 +215,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_northd, &en_sb_load_balancer, NULL);
     engine_add_input(&en_northd, &en_sb_fdb, NULL);
     engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL);
+    engine_add_input(&en_northd, &en_sb_template_var, NULL);
     engine_add_input(&en_lflow, &en_nb_bfd, NULL);
     engine_add_input(&en_lflow, &en_sb_bfd, NULL);
     engine_add_input(&en_lflow, &en_sb_logical_flow, NULL);
@@ -235,6 +240,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
         chassis_hostname_index_create(sb->idl);
     struct ovsdb_idl_index *sbrec_static_mac_binding_by_lport_ip
         = static_mac_binding_index_create(sb->idl);
+    struct ovsdb_idl_index *sbrec_template_var_by_name_chassis
+        = sbrec_template_var_by_name_chassis_index_create(sb->idl);
 
     engine_init(&en_lflow, &engine_arg);
 
@@ -256,6 +263,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_ovsdb_node_add_index(&en_sb_static_mac_binding,
                                 "sbrec_static_mac_binding_by_lport_ip",
                                 sbrec_static_mac_binding_by_lport_ip);
+    engine_ovsdb_node_add_index(&en_sb_template_var,
+                                "sbrec_template_var_by_name_chassis",
+                                sbrec_template_var_by_name_chassis);
 }
 
 void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn,
diff --git a/northd/northd.c b/northd/northd.c
index 0fcd3a642..c4769ea07 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -36,6 +36,7 @@
 #include "lib/ovn-sb-idl.h"
 #include "lib/ovn-util.h"
 #include "lib/lb.h"
+#include "lib/template-var.h"
 #include "memory.h"
 #include "northd.h"
 #include "lib/ovn-parallel-hmap.h"
@@ -14973,6 +14974,36 @@ sync_dns_entries(struct northd_input *input_data,
     }
     hmap_destroy(&dns_map);
 }
+
+static void
+sync_template_var(struct ovsdb_idl_txn *ovnsb_txn,
+                  struct ovsdb_idl_index *sbrec_template_var_by_name_chassis,
+                  const char *name, const char *value, const char *chassis)
+{
+    const struct sbrec_template_var *sb_tv =
+        sb_template_var_lookup_by_name_chassis(
+            sbrec_template_var_by_name_chassis, name, chassis);
+
+    if (!sb_tv) {
+        sb_tv = sbrec_template_var_insert(ovnsb_txn);
+        sbrec_template_var_set_name(sb_tv, name);
+        sbrec_template_var_set_chassis(sb_tv, chassis);
+    }
+    sbrec_template_var_set_value(sb_tv, value);
+}
+
+static void
+sync_template_vars(struct northd_input *input_data,
+                   struct ovsdb_idl_txn *ovnsb_txn)
+{
+    const struct nbrec_template_var *nb_tv;
+    NBREC_TEMPLATE_VAR_TABLE_FOR_EACH (nb_tv,
+                                       input_data->nbrec_template_var_table) {
+        sync_template_var(ovnsb_txn,
+                          input_data->sbrec_template_var_by_name_chassis,
+                          nb_tv->name, nb_tv->value, nb_tv->chassis);
+    }
+}
 
 static void
 destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ports,
@@ -15476,6 +15507,8 @@ ovnnb_db_run(struct northd_input *input_data,
     sync_port_groups(input_data, ovnsb_txn, &data->port_groups);
     sync_meters(input_data, ovnsb_txn, &data->meter_groups);
     sync_dns_entries(input_data, ovnsb_txn, &data->datapaths);
+    sync_template_vars(input_data, ovnsb_txn);
+
     cleanup_stale_fdb_entries(input_data, &data->datapaths);
     stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
 
diff --git a/northd/northd.h b/northd/northd.h
index 677b35877..33dd210fd 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -30,6 +30,7 @@ struct northd_input {
     const struct nbrec_acl_table *nbrec_acl_table;
     const struct nbrec_static_mac_binding_table
         *nbrec_static_mac_binding_table;
+    const struct nbrec_template_var_table *nbrec_template_var_table;
 
     /* Southbound table references */
     const struct sbrec_sb_global_table *sbrec_sb_global_table;
@@ -56,6 +57,7 @@ struct northd_input {
     struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name;
     struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;
     struct ovsdb_idl_index *sbrec_static_mac_binding_by_lport_ip;
+    struct ovsdb_idl_index *sbrec_template_var_by_name_chassis;
 };
 
 struct chassis_features {
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index 174364c8b..c38ed4f69 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
-    "version": "6.3.0",
-    "cksum": "4042813038 31869",
+    "version": "6.4.0",
+    "cksum": "337369157 32292",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -620,6 +620,16 @@
                 "mac": {"type": "string"},
                 "override_dynamic_mac": {"type": "boolean"}},
             "indexes": [["logical_port", "ip"]],
-             "isRoot": true}
+             "isRoot": true},
+        "Template_Var": {
+            "columns": {
+                "name": {"type": "string"},
+                "value": {"type": "string"},
+                "chassis": {"type": "string"},
+                "external_ids": {
+                    "type": {"key": "string", "value": "string",
+                             "min": 0, "max": "unlimited"}}},
+            "indexes": [["name", "chassis"]],
+            "isRoot": true}
     }
 }
diff --git a/ovn-nb.xml b/ovn-nb.xml
index e26afd83c..b9bfb59d4 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -4421,4 +4421,11 @@
       </column>
     </group>
   </table>
+
+  <table name="Template_Var">
+    <column name="name" />
+    <column name="value" />
+    <column name="chassis" />
+    <column name="external_ids" />
+  </table>
 </database>
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 3b78ea6f6..94487a894 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
-    "version": "20.23.0",
-    "cksum": "4045988377 28575",
+    "version": "20.24.0",
+    "cksum": "2495293843 28838",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -560,6 +560,13 @@
                                   "key": {"type": "uuid",
                                           "refTable": "Datapath_Binding"}}}},
             "indexes": [["logical_port", "ip"]],
+            "isRoot": true},
+        "Template_Var": {
+            "columns": {
+                "name": {"type": "string"},
+                "value": {"type": "string"},
+                "chassis": {"type": "string"}},
+            "indexes": [["name", "chassis"]],
             "isRoot": true}
     }
 }
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 59ad3aa2d..e991899bb 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -4739,4 +4739,10 @@ tcp.flags = RST;
       The logical datapath to which the logical router port belongs.
     </column>
   </table>
+
+  <table name="Template_Var">
+    <column name="name" />
+    <column name="value" />
+    <column name="chassis" />
+  </table>
 </database>
