diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index ae6e6c4ceb8dff695ddc51a839373c77413d8688..3b601fea6cee2d0d1b125aa406694cb2de2de1db 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -13,6 +13,7 @@ set(DEVICE_SRCS
 set(SRCS
   ${DEVICE_SRCS}
   base/ChainContext.cxx
+  base/DigiData.cxx
   base/Options.cxx
   base/MainConfig.cxx
   base/util/TimingsFormat.cxx
diff --git a/algo/base/DigiData.cxx b/algo/base/DigiData.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a76d0d07263365fe4814920eb0c70f5ed5b16e67
--- /dev/null
+++ b/algo/base/DigiData.cxx
@@ -0,0 +1,119 @@
+/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+#include "DigiData.h"
+
+using namespace cbm::algo;
+
+// Ctor / Dtor defined in .cxx file so we can use forward declarations for digi types in the header
+
+DigiData::DigiData() {}
+
+DigiData::~DigiData() {}
+
+DigiData::DigiData(const CbmDigiData& storable)
+  : fSts(ToPODVector(storable.fSts.fDigis))
+  , fMuch(ToPODVector(storable.fMuch.fDigis))
+  , fTof(ToPODVector(storable.fTof.fDigis))
+  , fBmon(ToPODVector(storable.fT0.fDigis))
+  , fTrd(ToPODVector(storable.fTrd.fDigis))
+  , fTrd2d(ToPODVector(storable.fTrd2d.fDigis))
+  , fRich(ToPODVector(storable.fRich.fDigis))
+  , fPsd(ToPODVector(storable.fPsd.fDigis))
+  , fFsd(ToPODVector(storable.fFsd.fDigis))
+{
+}
+
+size_t DigiData::Size(ECbmModuleId system) const
+{
+  switch (system) {
+    case ECbmModuleId::kSts: return fSts.size();
+    case ECbmModuleId::kMuch: return fMuch.size();
+    case ECbmModuleId::kTof: return fTof.size();
+    case ECbmModuleId::kT0: return fBmon.size();
+    case ECbmModuleId::kTrd: return fTrd.size();
+    case ECbmModuleId::kTrd2d: return fTrd2d.size();
+    case ECbmModuleId::kRich: return fRich.size();
+    case ECbmModuleId::kPsd: return fPsd.size();
+    case ECbmModuleId::kFsd: return fFsd.size();
+    default: throw std::runtime_error("DigiData: Invalid system Id " + ::ToString(system));
+  }
+}
+
+CbmDigiData DigiData::ToStorable() const
+{
+  return CbmDigiData {
+    .fT0 =
+      {
+        .fDigis = ToStdVector(fBmon),
+      },
+    .fSts =
+      {
+        .fDigis = ToStdVector(fSts),
+      },
+    .fMuch =
+      {
+        .fDigis = ToStdVector(fMuch),
+      },
+    .fRich =
+      {
+        .fDigis = ToStdVector(fRich),
+      },
+    .fTrd =
+      {
+        .fDigis = ToStdVector(fTrd),
+      },
+    .fTrd2d =
+      {
+        .fDigis = ToStdVector(fTrd2d),
+      },
+    .fTof =
+      {
+        .fDigis = ToStdVector(fTof),
+      },
+    .fPsd =
+      {
+        .fDigis = ToStdVector(fPsd),
+      },
+    .fFsd =
+      {
+        .fDigis = ToStdVector(fFsd),
+      },
+  };
+}
+
+std::vector<DigiEvent> DigiEvent::FromCbmDigiEvents(const std::vector<CbmDigiEvent>& events)
+{
+  std::vector<DigiEvent> result;
+  result.reserve(events.size());
+  for (const auto& event : events) {
+    result.emplace_back(event);
+  }
+  return result;
+}
+
+std::vector<CbmDigiEvent> DigiEvent::ToCbmDigiEvents(const std::vector<DigiEvent>& events)
+{
+  std::vector<CbmDigiEvent> result;
+  result.reserve(events.size());
+  for (const auto& event : events) {
+    result.emplace_back(event.ToStorable());
+  }
+  return result;
+}
+
+DigiEvent::DigiEvent(const CbmDigiEvent& storable)
+  : DigiData(storable.fData)
+  , fNumber(storable.fNumber)
+  , fTime(storable.fTime)
+{
+}
+
+CbmDigiEvent DigiEvent::ToStorable() const
+{
+  return CbmDigiEvent {
+    .fData   = DigiData::ToStorable(),
+    .fNumber = fNumber,
+    .fTime   = fTime,
+  };
+}
diff --git a/algo/base/DigiData.h b/algo/base/DigiData.h
index da3801d931ec7be855886c89db6e34a333ff5a31..6479e58e4d8d6e58eb67f4355c4dd2249f8156bd 100644
--- a/algo/base/DigiData.h
+++ b/algo/base/DigiData.h
@@ -4,11 +4,9 @@
 #ifndef CBM_ALGO_BASE_DIGI_DATA_H
 #define CBM_ALGO_BASE_DIGI_DATA_H
 
+#include "CbmBmonDigi.h"
 #include "CbmDigiData.h"
 #include "CbmDigiEvent.h"
-
-// TODO: we could also use forward declarations here for Digi types and make this header more lightweight
-#include "CbmBmonDigi.h"
 #include "CbmFsdDigi.h"
 #include "CbmMuchDigi.h"
 #include "CbmPsdDigi.h"
@@ -43,19 +41,10 @@ namespace cbm::algo
     PODVector<CbmPsdDigi> fPsd;    ///< Unpacked PSD digis
     PODVector<CbmFsdDigi> fFsd;    ///< Unpacked FSD digis
 
-    DigiData() = default;
+    DigiData();
+    ~DigiData();
 
-    explicit DigiData(const CbmDigiData& storable)
-      : fSts(ToPODVector(storable.fSts.fDigis))
-      , fMuch(ToPODVector(storable.fMuch.fDigis))
-      , fTof(ToPODVector(storable.fTof.fDigis))
-      , fBmon(ToPODVector(storable.fT0.fDigis))
-      , fTrd(ToPODVector(storable.fTrd.fDigis))
-      , fTrd2d(ToPODVector(storable.fTrd2d.fDigis))
-      , fRich(ToPODVector(storable.fRich.fDigis))
-      , fPsd(ToPODVector(storable.fPsd.fDigis))
-    {
-    }
+    explicit DigiData(const CbmDigiData& storable);
 
     /**
      * @brief Get the number of digis for a given subsystem
@@ -63,61 +52,14 @@ namespace cbm::algo
      * @param system Subsystem to get the number of digis for
      * @todo Should use fles::Subsystem instead ECbmModuleId
      */
-    size_t Size(ECbmModuleId system) const
-    {
-      switch (system) {
-        case ECbmModuleId::kSts: return fSts.size();
-        case ECbmModuleId::kMuch: return fMuch.size();
-        case ECbmModuleId::kTof: return fTof.size();
-        case ECbmModuleId::kT0: return fBmon.size();
-        case ECbmModuleId::kTrd: return fTrd.size();
-        case ECbmModuleId::kTrd2d: return fTrd2d.size();
-        case ECbmModuleId::kRich: return fRich.size();
-        case ECbmModuleId::kPsd: return fPsd.size();
-        case ECbmModuleId::kFsd: return fFsd.size();
-        default: throw std::runtime_error("DigiData: Invalid system Id " + ::ToString(system));
-      }
-    }
+    size_t Size(ECbmModuleId system) const;
 
     /**
      * @brief Convert to CbmDigiData for file storage
      *
      * @note This is a very expensive operation, as it copies all data.
      */
-    CbmDigiData ToStorable() const
-    {
-      return CbmDigiData {
-        .fT0 =
-          {
-            .fDigis = ToStdVector(fBmon),
-          },
-        .fSts =
-          {
-            .fDigis = ToStdVector(fSts),
-          },
-        .fMuch =
-          {
-            .fDigis = ToStdVector(fMuch),
-          },
-        .fTrd =
-          {
-            .fDigis = ToStdVector(fTrd),
-          },
-        .fTrd2d =
-          {
-            .fDigis = ToStdVector(fTrd2d),
-          },
-        .fTof =
-          {
-            .fDigis = ToStdVector(fTof),
-          },
-        .fPsd =
-          {
-            .fDigis = ToStdVector(fPsd),
-          },
-        .fFsd = {},
-      };
-    }
+    CbmDigiData ToStorable() const;
   };
 
   /**
@@ -130,48 +72,19 @@ namespace cbm::algo
     uint64_t fNumber;  ///< Event identifier
     double fTime;      ///< Event trigger time [ns]
 
-    static std::vector<DigiEvent> FromCbmDigiEvents(const std::vector<CbmDigiEvent>& events)
-    {
-      std::vector<DigiEvent> result;
-      result.reserve(events.size());
-      for (const auto& event : events) {
-        result.emplace_back(event);
-      }
-      return result;
-    }
-
-    static std::vector<CbmDigiEvent> ToCbmDigiEvents(const std::vector<DigiEvent>& events)
-    {
-      std::vector<CbmDigiEvent> result;
-      result.reserve(events.size());
-      for (const auto& event : events) {
-        result.emplace_back(event.ToStorable());
-      }
-      return result;
-    }
+    static std::vector<DigiEvent> FromCbmDigiEvents(const std::vector<CbmDigiEvent>& events);
+    static std::vector<CbmDigiEvent> ToCbmDigiEvents(const std::vector<DigiEvent>& events);
 
     DigiEvent() = default;
 
-    explicit DigiEvent(const CbmDigiEvent& storable)
-      : DigiData(storable.fData)
-      , fNumber(storable.fNumber)
-      , fTime(storable.fTime)
-    {
-    }
+    explicit DigiEvent(const CbmDigiEvent& storable);
 
     /**
    * @brief Convert to CbmDigiEvent for file storage
    *
    * @note This is a very expensive operation, as it copies all data.
    */
-    CbmDigiEvent ToStorable() const
-    {
-      return CbmDigiEvent {
-        .fData   = DigiData::ToStorable(),
-        .fNumber = fNumber,
-        .fTime   = fTime,
-      };
-    }
+    CbmDigiEvent ToStorable() const;
   };
 
 }  // namespace cbm::algo