diff --git a/setup.py b/setup.py
index 389c53da2b3ba212b4a1203c9821d541c94bf83b..ce8c3831bec85ac67369fea7350f657bd78fdfd2 100644
--- a/setup.py
+++ b/setup.py
@@ -32,6 +32,7 @@ setup(name='calng',
               'ManualDsscGeometry = calng.ManualDsscGeometry:ManualDsscGeometry',
               'ManualJungfrauGeometry = calng.ManualJungfrauGeometry:ManualJungfrauGeometry',
               'ShmemToZMQ = calng.ShmemToZMQ:ShmemToZMQ',
+              'ShmemTrainMatcher = calng.ShmemTrainMatcher:ShmemTrainMatcher',
               'DetectorAssembler = calng.DetectorAssembler:DetectorAssembler',
           ],
 
diff --git a/src/calng/CalibrationManager.py b/src/calng/CalibrationManager.py
index 245cb9731fd7c32e9b1d187a2acaaaee6fffe765..b78948b0fed20605cf1f00d0e8a559ec9d9bce41 100644
--- a/src/calng/CalibrationManager.py
+++ b/src/calng/CalibrationManager.py
@@ -71,15 +71,7 @@ class ClassIdsNode(Configurable):
         displayedName='Group matcher class',
         description='Device class to use for matching the stream output of a '
                     'module group.',
-        defaultValue='TrainMatcher',
-        accessMode=AccessMode.INITONLY,
-        assignment=Assignment.MANDATORY)
-
-    bridgeClass = String(
-        displayedName='Bridge class',
-        description='Device class to use for bridging the stream output out '
-                    'of Karabo.',
-        defaultValue='ShmemToZmq',
+        defaultValue='ShmemTrainMatcher',
         accessMode=AccessMode.INITONLY,
         assignment=Assignment.MANDATORY)
 
@@ -110,14 +102,6 @@ class DeviceIdsNode(Configurable):
         accessMode=AccessMode.INITONLY,
         assignment=Assignment.MANDATORY)
 
-    bridgeSuffix = String(
-        displayedName='Bridge suffix',
-        description='Suffix for group bridge device IDs. The formatting '
-                    'placeholder \'group\' may be used.',
-        defaultValue='BRIDGE_G{group}',
-        accessMode=AccessMode.INITONLY,
-        assignment=Assignment.MANDATORY)
-
     assemblerSuffix = String(
         displayedName='Assembler suffix',
         description='Suffix for assembler device IDs. The formatting '
@@ -1209,8 +1193,7 @@ class CalibrationManager(DeviceClientBase, Device):
         device_id_templates = {}
 
         class_args = (self.detectorType.value.lower().capitalize(),)
-        for role in ['correction', 'groupMatcher', 'bridge',
-                     'assembler']:
+        for role in ['correction', 'groupMatcher', 'assembler']:
             class_ids[role] = getattr(
                 self.classIds, f'{role}Class').value.format(*class_args)
             device_id_templates[role] = f'{self._device_id_root}/' + \
diff --git a/src/calng/ShmemTrainMatcher.py b/src/calng/ShmemTrainMatcher.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d481ccd1032f301dbfbe387dacf144fa02ef20f
--- /dev/null
+++ b/src/calng/ShmemTrainMatcher.py
@@ -0,0 +1,26 @@
+from karabo.bound import KARABO_CLASSINFO
+from TrainMatcher import TrainMatcher
+
+from . import shmem_utils
+from ._version import version as deviceVersion
+
+
+@KARABO_CLASSINFO("ShmemTrainMatcher", deviceVersion)
+class ShmemTrainMatcher(TrainMatcher.TrainMatcher):
+    def initialization(self):
+        super().initialization()
+        self._shmem_handler = shmem_utils.ShmemCircularBufferReceiver()
+
+    def on_matched_data(self, train_id, sources):
+        for source, (data, timestamp) in sources.items():
+            if data.has("calngShmemPaths"):
+                shmem_paths = list(data["calngShmemPaths"])
+                data.erase("calngShmemPaths")
+                for shmem_path in shmem_paths:
+                    if not data.has(shmem_path):
+                        self.log.INFO(f"Hash from {source} did not have {shmem_path}")
+                        continue
+                    dereferenced = self._shmem_handler.get(data[shmem_path])
+                    data[shmem_path] = dereferenced
+
+        super().on_matched_data(train_id, sources)