diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py
index a4deae971a..ed73ed20b4 100644
--- a/ironic/drivers/modules/deploy_utils.py
+++ b/ironic/drivers/modules/deploy_utils.py
@@ -735,19 +735,22 @@ def get_pxe_config_template(node):
     """Return the PXE config template file name requested for deploy.
 
     This method returns PXE config template file to be used for deploy.
-    Architecture specific template file is searched first. BIOS/UEFI
-    template file is used if no valid architecture specific file found.
+    First specific pxe template is searched in the node. After that
+    architecture specific template file is searched. BIOS/UEFI template file
+    is used if no valid architecture specific file found.
 
     :param node: A single Node.
     :returns: The PXE config template file name.
     """
-    cpu_arch = node.properties.get('cpu_arch')
-    config_template = CONF.pxe.pxe_config_template_by_arch.get(cpu_arch)
+    config_template = node.driver_info.get("pxe_template", None)
     if config_template is None:
-        if boot_mode_utils.get_boot_mode(node) == 'uefi':
-            config_template = CONF.pxe.uefi_pxe_config_template
-        else:
-            config_template = CONF.pxe.pxe_config_template
+        cpu_arch = node.properties.get('cpu_arch')
+        config_template = CONF.pxe.pxe_config_template_by_arch.get(cpu_arch)
+        if config_template is None:
+            if boot_mode_utils.get_boot_mode(node) == 'uefi':
+                config_template = CONF.pxe.uefi_pxe_config_template
+            else:
+                config_template = CONF.pxe.pxe_config_template
 
     return config_template
 
diff --git a/ironic/tests/unit/drivers/modules/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
index d51885a692..4f6d828103 100644
--- a/ironic/tests/unit/drivers/modules/test_deploy_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
@@ -1113,6 +1113,14 @@ class GetPxeBootConfigTestCase(db_base.DbTestCase):
         result = utils.get_pxe_config_template(self.node)
         self.assertEqual('bios-template', result)
 
+    def test_get_pxe_config_template_per_node(self):
+        node = obj_utils.create_test_node(
+            self.context, driver='fake-hardware',
+            driver_info={"pxe_template": "fake-template"},
+        )
+        result = utils.get_pxe_config_template(node)
+        self.assertEqual('fake-template', result)
+
 
 @mock.patch('time.sleep', lambda sec: None)
 class OtherFunctionTestCase(db_base.DbTestCase):
diff --git a/releasenotes/notes/add-pxe-per-node-526fd79df17efda8.yaml b/releasenotes/notes/add-pxe-per-node-526fd79df17efda8.yaml
new file mode 100644
index 0000000000..d73ae511d4
--- /dev/null
+++ b/releasenotes/notes/add-pxe-per-node-526fd79df17efda8.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    Add a new field pxe_template that can be set at driver-info level. This
+    will specify a path for a custom pxe boot template. If present, this
+    template will be read and will have priority in front of the per-arch and
+    general pxe templates.
+