diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 46ba5e30b5..a3c1348157 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -582,6 +582,7 @@ struct _virQEMUCaps {
 
     virArch arch;
 
+    virHashTablePtr domCapsCache;
     virDomainCapsCPUModelsPtr kvmCPUModels;
     virDomainCapsCPUModelsPtr tcgCPUModels;
 
@@ -1476,6 +1477,9 @@ virQEMUCapsNew(void)
     if (!(qemuCaps->flags = virBitmapNew(QEMU_CAPS_LAST)))
         goto error;
 
+    if (!(qemuCaps->domCapsCache = virHashCreate(5, virObjectFreeHashData)))
+        goto error;
+
     return qemuCaps;
 
  error:
@@ -1628,6 +1632,7 @@ void virQEMUCapsDispose(void *obj)
     }
     VIR_FREE(qemuCaps->machineTypes);
 
+    virHashFree(qemuCaps->domCapsCache);
     virObjectUnref(qemuCaps->kvmCPUModels);
     virObjectUnref(qemuCaps->tcgCPUModels);
 
@@ -1790,6 +1795,12 @@ const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps)
 }
 
 
+virHashTablePtr virQEMUCapsGetDomainCapsCache(virQEMUCapsPtr qemuCaps)
+{
+    return qemuCaps->domCapsCache;
+}
+
+
 int
 virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
                              virDomainVirtType type,
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index c6f6980684..2a37f0c2ff 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -538,6 +538,7 @@ const char *virQEMUCapsGetBinary(virQEMUCapsPtr qemuCaps);
 virArch virQEMUCapsGetArch(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetVersion(virQEMUCapsPtr qemuCaps);
 const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps);
+virHashTablePtr virQEMUCapsGetDomainCapsCache(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetKVMVersion(virQEMUCapsPtr qemuCaps);
 int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
                                  virDomainVirtType type,
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 635fdcc5a4..6a7c183075 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1358,10 +1358,39 @@ virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
 }
 
 
+struct virQEMUDriverSearchDomcapsData {
+    const char *path;
+    const char *machine;
+    virArch arch;
+    virDomainVirtType virttype;
+};
+
+
+static int
+virQEMUDriverSearchDomcaps(const void *payload,
+                           const void *name ATTRIBUTE_UNUSED,
+                           const void *opaque)
+{
+    virDomainCapsPtr domCaps = (virDomainCapsPtr) payload;
+    struct virQEMUDriverSearchDomcapsData *data = (struct virQEMUDriverSearchDomcapsData *) opaque;
+
+    if (STREQ_NULLABLE(data->path, domCaps->path) &&
+        STREQ_NULLABLE(data->machine, domCaps->machine) &&
+        data->arch == domCaps->arch &&
+        data->virttype == domCaps->virttype)
+        return 1;
+
+    return 0;
+}
+
 /**
  * virQEMUDriverGetDomainCapabilities:
  *
- * Build a virDomainCapsPtr instance for the passed data.
+ * Get a reference to the virDomainCapsPtr instance from the virQEMUCapsPtr
+ * domCapsCache. If there's no domcaps in the cache, create a new instance,
+ * add it to the cache, and return a reference.
+ *
+ * The caller must release the reference with virObjetUnref
  *
  * Returns: a reference to a virDomainCapsPtr instance or NULL
  */
@@ -1375,18 +1404,34 @@ virQEMUDriverGetDomainCapabilities(virQEMUDriverPtr driver,
     virDomainCapsPtr ret = NULL, domCaps = NULL;
     virCapsPtr caps = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    virHashTablePtr domCapsCache = virQEMUCapsGetDomainCapsCache(qemuCaps);
+    struct virQEMUDriverSearchDomcapsData data = {
+        .path = virQEMUCapsGetBinary(qemuCaps),
+        .machine = machine,
+        .arch = arch,
+        .virttype = virttype,
+    };
 
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto cleanup;
 
-    if (!(domCaps = virDomainCapsNew(virQEMUCapsGetBinary(qemuCaps), machine,
-                                     arch, virttype)))
-        goto cleanup;
+    domCaps = virHashSearch(domCapsCache,
+                            virQEMUDriverSearchDomcaps, &data, NULL);
+    if (!domCaps) {
+        /* hash miss, build new domcaps */
+        if (!(domCaps = virDomainCapsNew(data.path, data.machine,
+                                         data.arch, data.virttype)))
+            goto cleanup;
 
-    if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
-                                  cfg->firmwares, cfg->nfirmwares) < 0)
-        goto cleanup;
+        if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
+                                      cfg->firmwares, cfg->nfirmwares) < 0)
+            goto cleanup;
+
+        if (virHashAddEntry(domCapsCache, machine, domCaps) < 0)
+            goto cleanup;
+    }
 
+    virObjectRef(domCaps);
     VIR_STEAL_PTR(ret, domCaps);
  cleanup:
     virObjectUnref(domCaps);
