diff --git a/nomad/datamodel/datamodel.py b/nomad/datamodel/datamodel.py
index 0249e890ba0c9b50fc8003d66cc1ae2c166ff9dd..961988022412860c86a9da2c0c4b3c34c0bc62e0 100644
--- a/nomad/datamodel/datamodel.py
+++ b/nomad/datamodel/datamodel.py
@@ -228,6 +228,21 @@ def derive_authors(entry: 'EntryMetadata') -> List[User]:
     return authors
 
 
+class CompatibleSectionDef(MSection):
+    definition_qualified_name = Quantity(
+        type=str,
+        description='The qualified name of the compatible section.',
+        a_elasticsearch=Elasticsearch(material_entry_type))
+    definition_id = Quantity(
+        type=str,
+        description='The definition id of the compatible section.',
+        a_elasticsearch=Elasticsearch(material_entry_type))
+    used_directly = Quantity(
+        type=bool,
+        description='If the compatible section is directly used as base section.',
+        a_elasticsearch=Elasticsearch(material_entry_type))
+
+
 class EntryArchiveReference(MSection):
     m_def = Section(label='ArchiveReference')
 
@@ -643,9 +658,15 @@ class EntryMetadata(MSection):
 
     sections = Quantity(
         type=str, shape=['*'],
-        description='All sections that are present in this entry.',
+        description='All sections that are present in this entry. This field is deprecated and will be removed.',
         a_elasticsearch=Elasticsearch(material_entry_type))
 
+    section_defs = SubSection(
+        sub_section=CompatibleSectionDef,
+        repeats=True,
+        description='All sections that are compatible with the present sections in this entry.',
+        a_elasticsearch=Elasticsearch(material_entry_type, nested=True))
+
     entry_references = SubSection(
         sub_section=EntryArchiveReference,
         repeats=True,
@@ -826,7 +847,7 @@ class EntryMetadata(MSection):
         if len(entry_references) > 0:
             for archive_reference_quantity in EntryArchiveReference.m_def.quantities:  # pylint: disable=not-an-iterable
                 quantities.add(f'metadata.entry_references.{archive_reference_quantity.name}')
-                quantities.add('metadata.entry_references')
+            quantities.add('metadata.entry_references')
             sections.add(EntryArchiveReference.m_def)
 
         if len(quantities) > 0:
@@ -834,6 +855,9 @@ class EntryMetadata(MSection):
 
         if len(sections) > 0:
             quantities.add('metadata.sections')
+            quantities.add('metadata.section_defs')
+            for compatible_quantity in CompatibleSectionDef.m_def.quantities:
+                quantities.add(f'metadata.section_defs.{compatible_quantity.name}')
 
         self.entry_references.extend(entry_references)
         self.searchable_quantities.extend(searchable_quantities)
@@ -843,6 +867,32 @@ class EntryMetadata(MSection):
         self.sections.sort()
         self.n_quantities = n_quantities
 
+        def generate_compatible(_s, used_directly: bool):
+            return CompatibleSectionDef(
+                definition_qualified_name=_s.qualified_name(),
+                definition_id=_s.definition_id,
+                used_directly=used_directly)
+
+        def collect_base_sections(_section, used_directly: bool = False):
+            for _b in _section.base_sections:
+                if used_directly:
+                    # always overrides the directly used section definitions
+                    section_defs[_b.qualified_name()] = generate_compatible(_b, used_directly=used_directly)
+                elif _b.qualified_name() not in section_defs:
+                    # indirect usage may be directly used elsewhere, do not overwrite
+                    section_defs[_b.qualified_name()] = generate_compatible(_b, used_directly=used_directly)
+                # all the base sections of the base sections are indirectly used
+                collect_base_sections(_b, used_directly=False)
+
+        section_defs = {}
+        for section in sections:
+            section_defs[section.qualified_name()] = generate_compatible(section, used_directly=True)
+            for extending in section.extending_sections:
+                section_defs[extending.qualified_name()] = generate_compatible(extending, used_directly=True)
+            collect_base_sections(section, used_directly=True)
+
+        self.section_defs = sorted(list(section_defs.values()), key=lambda x: x.definition_qualified_name)
+
 
 class EntryArchive(ArchiveSection):
     m_def = Section(label='Entry')
diff --git a/tests/datamodel/test_datamodel.py b/tests/datamodel/test_datamodel.py
index a187770f818186ee162c5d8d6f17b11c98e7ba55..4453066ebbe1dd724d70f5f0588934433a016d24 100644
--- a/tests/datamodel/test_datamodel.py
+++ b/tests/datamodel/test_datamodel.py
@@ -19,10 +19,11 @@
 '''
 A generator for random test calculations.
 '''
-
 import random
 from essential_generators import DocumentGenerator
 
+from nomad.datamodel import EntryArchive, EntryMetadata
+from nomad.metainfo import MSection, Quantity, SubSection
 from nomad.parsing.parsers import parser_dict
 
 number_of = 20
@@ -30,7 +31,8 @@ number_of = 20
 random.seed(0)
 gen = DocumentGenerator()
 
-users = ['20bb9766-d338-4314-be43-7906042a5086', 'a03af8b6-3aa7-428a-b3b1-4a6317e576b6', '54cb1f64-f84e-4815-9ade-440ce0b5430f']
+users = ['20bb9766-d338-4314-be43-7906042a5086', 'a03af8b6-3aa7-428a-b3b1-4a6317e576b6',
+         '54cb1f64-f84e-4815-9ade-440ce0b5430f']
 basis_sets = ['Numeric AOs', 'Gaussians', '(L)APW+lo', 'Plane waves']
 xc_functionals = ['LDA', 'GGA', 'hybrid', 'meta-GGA', 'GW', 'unknown']
 crystal_systems = ['triclinic', 'monoclinic', 'orthorombic', 'tetragonal', 'hexagonal', 'cubic']