diff --git a/Event/EventPacker/CMakeLists.txt b/Event/EventPacker/CMakeLists.txt
index 7f15a8b6533756e4a02bd6921c3289cd89bc8cf3..fbf3143d79dc7f5197374b17138e363502da630f 100644
--- a/Event/EventPacker/CMakeLists.txt
+++ b/Event/EventPacker/CMakeLists.txt
@@ -64,6 +64,7 @@ gaudi_add_module(EventPacker
     SOURCES
         src/component/ErrorCategory.cpp
         src/component/SelectivePacker.cpp
+        src/component/RelationPackers.cpp
         src/component/BufferUnpackerBaseAlg.cpp
         src/component/DumpTracks.cpp
         src/component/PackMCParticle.cpp
@@ -74,6 +75,7 @@ gaudi_add_module(EventPacker
         src/component/UnpackRecVertex.cpp
         src/component/MCPackers.cpp
         src/component/Unpackers.cpp
+        src/component/BufferUnpackers.cpp
         src/component/PackedDataChecksum.cpp
     LINK
         Boost::headers
diff --git a/Event/EventPacker/include/Event/PackedCaloAdc.h b/Event/EventPacker/include/Event/PackedCaloAdc.h
index f45525ac68d5eb1ee9daf8570d7862c291a04b5d..946688de6e6e46fcc88e43e5f56b5c779e81530a 100644
--- a/Event/EventPacker/include/Event/PackedCaloAdc.h
+++ b/Event/EventPacker/include/Event/PackedCaloAdc.h
@@ -106,6 +106,9 @@ namespace LHCb {
       buf.load( m_adcs, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedCaloAdcs&, CaloAdcs& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedCaloCluster.h b/Event/EventPacker/include/Event/PackedCaloCluster.h
index 733d59c359ed4535381b2d298d4fe35f981fa1fd..7d78dd51f7074aa87db233e601c2e4760cd5791d 100644
--- a/Event/EventPacker/include/Event/PackedCaloCluster.h
+++ b/Event/EventPacker/include/Event/PackedCaloCluster.h
@@ -152,6 +152,9 @@ namespace LHCb {
       buf.load( m_entries, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedCaloClusters&, CaloClusters& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedCaloDigit.h b/Event/EventPacker/include/Event/PackedCaloDigit.h
index 0520cd444cdf3f66e1467afe4538e6e1f24f3fe0..490f826264ef79b1f65d2f4ea7ef749aae126370 100644
--- a/Event/EventPacker/include/Event/PackedCaloDigit.h
+++ b/Event/EventPacker/include/Event/PackedCaloDigit.h
@@ -107,6 +107,9 @@ namespace LHCb {
       buf.load( m_digits, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedCaloDigits&, CaloDigits& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedCaloHypo.h b/Event/EventPacker/include/Event/PackedCaloHypo.h
index 4a13d83be0d5c78570926789cfb3bc3891565eae..9fc6ca5027a39393e8fe9d06167cd674a1701cfe 100644
--- a/Event/EventPacker/include/Event/PackedCaloHypo.h
+++ b/Event/EventPacker/include/Event/PackedCaloHypo.h
@@ -130,6 +130,9 @@ namespace LHCb {
       buf.load( m_refs );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedCaloHypos&, CaloHypos& );
+
   private:
     std::vector<PackedCaloHypo> m_vect;
     std::vector<std::int64_t>   m_refs;
diff --git a/Event/EventPacker/include/Event/PackedFlavourTag.h b/Event/EventPacker/include/Event/PackedFlavourTag.h
index 00e2cc7eb524e1c72c8c3ed932601af2940eb6eb..e53720d52bf1187b86dc63d83b639a449143d1c0 100644
--- a/Event/EventPacker/include/Event/PackedFlavourTag.h
+++ b/Event/EventPacker/include/Event/PackedFlavourTag.h
@@ -166,6 +166,9 @@ namespace LHCb {
       buf.load( m_taggingPs );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedFlavourTags&, FlavourTags& );
+
   private:
     /// Data packing version (not used as yet, but for any future schema evolution)
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedMuonPID.h b/Event/EventPacker/include/Event/PackedMuonPID.h
index 5c5944ebcc601aac92ba3aca9253c4bd9bd45b6d..5fa64179ac73e74666d143e8cd189ce9d3ff4595 100644
--- a/Event/EventPacker/include/Event/PackedMuonPID.h
+++ b/Event/EventPacker/include/Event/PackedMuonPID.h
@@ -119,6 +119,9 @@ namespace LHCb {
       buf.load( m_vect, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedMuonPIDs&, MuonPIDs& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedPartToRelatedInfoRelation.h b/Event/EventPacker/include/Event/PackedPartToRelatedInfoRelation.h
index 17935cf8547ea9247bb1e05bed02fe02e344e9bd..c991a98fa8c5de60d8a7928af541fcf700a54836 100644
--- a/Event/EventPacker/include/Event/PackedPartToRelatedInfoRelation.h
+++ b/Event/EventPacker/include/Event/PackedPartToRelatedInfoRelation.h
@@ -134,6 +134,10 @@ namespace LHCb {
       buf.load( m_containers, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedRelatedInfoRelations&,
+                        Relation1D<Particle, RelatedInfoMap>& );
+
   private:
     /// Data packing version (not used as yet, but for any future schema evolution)
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedParticle.h b/Event/EventPacker/include/Event/PackedParticle.h
index 3a988f1d9e6ffd99c7a28cf0ed15708cb087d457..3167fd13df03ec431e18a4f8a6c339903cb92e01 100644
--- a/Event/EventPacker/include/Event/PackedParticle.h
+++ b/Event/EventPacker/include/Event/PackedParticle.h
@@ -162,6 +162,9 @@ namespace LHCb {
       buf.load( m_daughters );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedParticles&, Particles& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedProtoParticle.h b/Event/EventPacker/include/Event/PackedProtoParticle.h
index 44e48587e384e7ec4fd17e59a4cb0f197ec455e4..1e6f78fc995d1b5a6fd727e5438076c4af3856dc 100644
--- a/Event/EventPacker/include/Event/PackedProtoParticle.h
+++ b/Event/EventPacker/include/Event/PackedProtoParticle.h
@@ -119,6 +119,9 @@ namespace LHCb {
       buf.load( m_extra, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedProtoParticles&, ProtoParticles& );
+
   private:
     std::vector<PackedProtoParticle> m_vect;
     std::vector<std::int64_t>        m_refs;
diff --git a/Event/EventPacker/include/Event/PackedRecSummary.h b/Event/EventPacker/include/Event/PackedRecSummary.h
index b0719f5b7dfa5a5a133df4e956fc0147469d1ce7..55a582770077df09f9e798c5d1d8ea32578bd195 100644
--- a/Event/EventPacker/include/Event/PackedRecSummary.h
+++ b/Event/EventPacker/include/Event/PackedRecSummary.h
@@ -83,6 +83,9 @@ namespace LHCb {
       buf.load( m_vect );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedRecSummary&, RecSummary& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedRecVertex.h b/Event/EventPacker/include/Event/PackedRecVertex.h
index d4d7158ee4142c9abf0a29c9d55d167d91578cb8..0f5754cca9d1e17ca38b65f750265661a415bdde 100644
--- a/Event/EventPacker/include/Event/PackedRecVertex.h
+++ b/Event/EventPacker/include/Event/PackedRecVertex.h
@@ -145,6 +145,9 @@ namespace LHCb {
       buf.load( m_weights );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedRecVertices&, RecVertices& );
+
   private:
     std::vector<PackedRecVertex>     m_vect;
     std::vector<std::int64_t>        m_refs;
diff --git a/Event/EventPacker/include/Event/PackedRichPID.h b/Event/EventPacker/include/Event/PackedRichPID.h
index 09fd46c3a2751fbd84beb204ec9104a555ce84ce..b32f7d778f29e0a5169c98331e3cbc99fbe082f3 100644
--- a/Event/EventPacker/include/Event/PackedRichPID.h
+++ b/Event/EventPacker/include/Event/PackedRichPID.h
@@ -122,6 +122,9 @@ namespace LHCb {
       buf.load( m_vect, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedRichPIDs&, RichPIDs& );
+
   private:
     /// Data packing version
     std::int8_t m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedSharedObjectsContainer.h b/Event/EventPacker/include/Event/PackedSharedObjectsContainer.h
index 770d31de0cbb824219a7cd87a0342614db05cec7..df47c3aa280d66fb158ae88fe80397a5062f09f6 100644
--- a/Event/EventPacker/include/Event/PackedSharedObjectsContainer.h
+++ b/Event/EventPacker/include/Event/PackedSharedObjectsContainer.h
@@ -16,7 +16,6 @@
 // Include files
 namespace LHCb {
 
-
   /** @class PackedSharedObjectsContainer PackedSharedObjectsContainer.h Event/PackedSharedObjectsContainer.h
    *
    *  Packed SharedObjectsContainer
@@ -29,11 +28,10 @@ namespace LHCb {
     /// Class ID
     static CLID classID();
 
-
     /// Class ID
     const CLID& clID() const override {
-        static const CLID id = classID();
-        return id;
+      static const CLID id = classID();
+      return id;
     }
     /// packing version
     static char packingVersion() { return 0; }
@@ -74,20 +72,46 @@ namespace LHCb {
   };
 
   class CaloCluster;
-  template <> inline CLID PackedSharedObjectsContainer< CaloCluster   >::classID() {  return 1841; }
-  namespace Event { class Track; }
-  template <> inline CLID PackedSharedObjectsContainer< Track         >::classID() {  return 1850; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<CaloCluster>::classID() {
+    return 1841;
+  }
+  namespace Event {
+    class Track;
+  }
+  template <>
+  inline CLID PackedSharedObjectsContainer<Track>::classID() {
+    return 1850;
+  }
   class CaloHypo;
-  template <> inline CLID PackedSharedObjectsContainer< CaloHypo      >::classID() {  return 1851; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<CaloHypo>::classID() {
+    return 1851;
+  }
   class RecVertex;
-  template <> inline CLID PackedSharedObjectsContainer< RecVertex     >::classID() {  return 1853; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<RecVertex>::classID() {
+    return 1853;
+  }
   class TwoProngVertex;
-  template <> inline CLID PackedSharedObjectsContainer< TwoProngVertex>::classID() {  return 1854; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<TwoProngVertex>::classID() {
+    return 1854;
+  }
   class Particle;
-  template <> inline CLID PackedSharedObjectsContainer< Particle      >::classID() {  return 1881; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<Particle>::classID() {
+    return 1881;
+  }
   class Vertex;
-  template <> inline CLID PackedSharedObjectsContainer< Vertex        >::classID() {  return 1882; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<Vertex>::classID() {
+    return 1882;
+  }
   class FlavourTag;
-  template <> inline CLID PackedSharedObjectsContainer< FlavourTag    >::classID() {  return 1883; }
+  template <>
+  inline CLID PackedSharedObjectsContainer<FlavourTag>::classID() {
+    return 1883;
+  }
 
 } // namespace LHCb
diff --git a/Event/EventPacker/include/Event/PackedTrack.h b/Event/EventPacker/include/Event/PackedTrack.h
index 7f1c542b4cee19be6ed8fdd77e708f59dd8b16bc..3436a8f1d4d3ffbb5cfcfb31509d4e7c15736399 100644
--- a/Event/EventPacker/include/Event/PackedTrack.h
+++ b/Event/EventPacker/include/Event/PackedTrack.h
@@ -200,6 +200,9 @@ namespace LHCb {
       buf.load( m_extra, ver );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedTracks&, Tracks& );
+
   private:
     std::vector<PackedTrack>                           m_vect;
     std::vector<PackedState>                           m_state;
diff --git a/Event/EventPacker/include/Event/PackedTwoProngVertex.h b/Event/EventPacker/include/Event/PackedTwoProngVertex.h
index 69e96bbd97c3d50c56195de91acbdf1daa067068..77e0843d68c03071194dc353b88f6dbfb148c63f 100644
--- a/Event/EventPacker/include/Event/PackedTwoProngVertex.h
+++ b/Event/EventPacker/include/Event/PackedTwoProngVertex.h
@@ -160,6 +160,9 @@ namespace LHCb {
       buf.load( m_extra, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedTwoProngVertices&, TwoProngVertices& );
+
   private:
     std::vector<PackedTwoProngVertex> m_vect;
     std::vector<std::int64_t>         m_refs;
diff --git a/Event/EventPacker/include/Event/PackedVertex.h b/Event/EventPacker/include/Event/PackedVertex.h
index e9f3b5e9e0495c3eb6a37de385663dac41300ccb..a7fd69cfd88696999ba008211132091d776c204a 100644
--- a/Event/EventPacker/include/Event/PackedVertex.h
+++ b/Event/EventPacker/include/Event/PackedVertex.h
@@ -156,6 +156,9 @@ namespace LHCb {
       buf.load( m_extra, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedVertices&, Vertices& );
+
   private:
     /// Data packing version
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/include/Event/PackedWeightsVector.h b/Event/EventPacker/include/Event/PackedWeightsVector.h
index d2fda3caef2d5d9540fbb7235d2f01debded7ef1..ba0e20826e4ad35ba7dccf34f0fe1082880f36fc 100644
--- a/Event/EventPacker/include/Event/PackedWeightsVector.h
+++ b/Event/EventPacker/include/Event/PackedWeightsVector.h
@@ -129,6 +129,9 @@ namespace LHCb {
       buf.load( m_weights, m_packingVersion );
     }
 
+    // perform unpacking
+    friend void unpack( Gaudi::Algorithm const*, const PackedWeightsVector&, WeightsVectors& );
+
   private:
     /// Data packing version (not used as yet, but for any future schema evolution)
     char m_packingVersion{defaultPackingVersion()};
diff --git a/Event/EventPacker/src/component/BufferUnpackerBaseAlg.cpp b/Event/EventPacker/src/component/BufferUnpackerBaseAlg.cpp
index d69e774b959cf67df62819dfb833a67c296a87a6..df4a2856faefffb11d006f77776a7e8dab6a4742 100644
--- a/Event/EventPacker/src/component/BufferUnpackerBaseAlg.cpp
+++ b/Event/EventPacker/src/component/BufferUnpackerBaseAlg.cpp
@@ -10,17 +10,22 @@
 \*****************************************************************************/
 #include "BufferUnpackerBaseAlg.h"
 
+using namespace LHCb::Packers::Traits;
+using namespace LHCb::Hlt::PackedData;
+
 namespace {
-  template <typename ... PACKER >
+  template <typename... DataVector>
   struct Create_t {
     auto operator()() const {
-      std::map<CLID, LHCb::Hlt::PackedData::LoaderFn_t> loaders;
-      ( loaders.emplace( PACKER::PackedDataVector::classID(), &LHCb::Hlt::PackedData::resolveObject<typename PACKER::DataVector, typename PACKER::PackedDataVector> ), ... );
+      std::map<CLID, LoaderFn_t> loaders;
+      ( loaders.emplace( packed_container<DataVector>::classID(),
+                         &resolveObject<DataVector, packed_container<DataVector>> ),
+        ... );
       return loaders;
     }
   };
-}
+} // namespace
 
 namespace LHCb::Hlt::PackedData {
-  const std::map<CLID, LoaderFn_t> Loader::s_map = LHCb::Packers::Traits::Expand<Create_t, LHCb::Packers::Traits::packer >{}();
+  const std::map<CLID, LoaderFn_t> Loader::s_map = Expand<Create_t, container>{}();
 }
diff --git a/Event/EventPacker/src/component/BufferUnpackerBaseAlg.h b/Event/EventPacker/src/component/BufferUnpackerBaseAlg.h
index 98d324f2fff78f1120de30505665e5bc4d3423df..3fc2829dc6a4872616c773981a893018c80af72f 100644
--- a/Event/EventPacker/src/component/BufferUnpackerBaseAlg.h
+++ b/Event/EventPacker/src/component/BufferUnpackerBaseAlg.h
@@ -33,8 +33,8 @@
 #include "RawbankV2Compatibility.h"
 #include "RegistryWrapper.h"
 #include "RelationPackers.h"
-#include "expected.h"
 #include "Traits.h"
+#include "expected.h"
 
 namespace {
   static const Gaudi::StringKey PackedObjectLocations{"PackedObjectLocations"};
@@ -282,8 +282,8 @@ namespace LHCb::Hlt::PackedData {
   };
 
   template <typename DataVector, typename PackedDataVector>
-  Expected<std::unique_ptr<DataVector>> restoreObject( PackedDataInBuffer& buffer,
-                                                       ObjectHeader const& header, Loader& loader ) {
+  Expected<std::unique_ptr<DataVector>> restoreObject( PackedDataInBuffer& buffer, ObjectHeader const& header,
+                                                       Loader& loader ) {
     // Sadly the pack structure expects data with valid Registry and LinkMgr. To be improved
     auto pdata      = DataPacking::Buffer::RegistryWrapper<PackedDataVector>( "DummyPacked" );
     auto nBytesRead = buffer.load( *pdata );
@@ -300,18 +300,18 @@ namespace LHCb::Hlt::PackedData {
     }
     if ( auto sc = loader.resolveLinks( *pdata, header ); sc.isFailure() )
       return Unexpected{sc}; // we may want to continue here, and have the unpacker deal with this...
-    auto   data = std::make_unique<DataVector>();
+    auto data = std::make_unique<DataVector>();
     data->setVersion( pdata->version() );
-    Packers::Traits::packer<DataVector>{loader}.unpack( *pdata, *data );
+    unpack( loader, *pdata, *data );
     return data;
   }
 
   template <typename DataVector, typename PackedDataVector>
-  Expected<std::unique_ptr<DataVector>> restoreObject( PackedDataInBuffer const& buffer,
-                                                                        Loader&                   loader ) {
+  Expected<std::unique_ptr<DataVector>> restoreObject( PackedDataInBuffer const& buffer, Loader& loader ) {
     auto readBuffer =
         ReadBuffer{buffer}; // TODO: allow for emphemeral 'view' for reading without copying just to update 'pos'
-    return LHCb::Hlt::PackedData::restoreObject<DataVector,PackedDataVector>( readBuffer, ObjectHeader{readBuffer}, loader );
+    return LHCb::Hlt::PackedData::restoreObject<DataVector, PackedDataVector>( readBuffer, ObjectHeader{readBuffer},
+                                                                               loader );
   }
 
   template <typename DataVector, typename PackedDataVector>
@@ -322,14 +322,13 @@ namespace LHCb::Hlt::PackedData {
                                                                                         // the tables if v2 instead...
     if ( !loc ) return Unexpected{ErrorCode::UNKNOWN_LOCATIONID};
     if ( auto obj = loader.get( *loc ); obj ) return std::pair{*loc, *obj};
-    auto obj = restoreObject<DataVector,PackedDataVector>( buffer, header, loader );
+    auto obj = restoreObject<DataVector, PackedDataVector>( buffer, header, loader );
     if ( !obj ) return Unexpected{obj.error()};
     auto ptr = obj->get();
     if ( auto sc = loader.put( *loc, std::move( *obj ) ); sc.isFailure() ) return Unexpected{sc};
     return std::pair{*loc, ptr};
   }
 
-
 } // namespace LHCb::Hlt::PackedData
 
 /**
@@ -423,7 +422,8 @@ namespace DataPacking::Buffer {
           m_data.put( std::make_unique<typename PACKER::DataVector>() ); // really do not want to do this...
         return;
       }
-      auto obj = LHCb::Hlt::PackedData::restoreObject<typename PACKER::DataVector, typename PACKER::PackedDataVector>( *buffer, loader );
+      auto obj = LHCb::Hlt::PackedData::restoreObject<typename PACKER::DataVector, typename PACKER::PackedDataVector>(
+          *buffer, loader );
       if ( !obj ) {
         if ( m_emptyContainerForFailedUnpacking ) {
           m_data.put( std::make_unique<typename PACKER::DataVector>() ); // really do not want to do this...
diff --git a/Event/EventPacker/src/component/BufferUnpackers.cpp b/Event/EventPacker/src/component/BufferUnpackers.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bd461a74f5da2d221550068ac405f0f94b7118c5
--- /dev/null
+++ b/Event/EventPacker/src/component/BufferUnpackers.cpp
@@ -0,0 +1,84 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2022 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#include "BufferSOAUnpackerBaseAlg.h"
+#include "BufferUnpackerBaseAlg.h"
+#include "RelationPackers.h"
+
+#include "Event/PackedCaloAdc.h"
+#include "Event/PackedCaloCluster.h"
+#include "Event/PackedCaloDigit.h"
+#include "Event/PackedCaloHypo.h"
+#include "Event/PackedFlavourTag.h"
+#include "Event/PackedMuonPID.h"
+#include "Event/PackedPartToRelatedInfoRelation.h"
+#include "Event/PackedParticle.h"
+#include "Event/PackedProtoParticle.h"
+#include "Event/PackedRecSummary.h"
+#include "Event/PackedRecVertex.h"
+#include "Event/PackedRelations.h"
+#include "Event/PackedRichPID.h"
+#include "Event/PackedTrack.h"
+#include "Event/PackedTwoProngVertex.h"
+#include "Event/PackedVertex.h"
+#include "Event/PackedWeightsVector.h"
+
+#include "Event/CaloClusters_v2.h"
+#include "Event/CaloHypos_v2.h"
+#include "Event/Track_v3.h"
+
+namespace DataPacking::Buffer {
+  // These packers take one data buffer location and produce unpacked object
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RecVertexPacker>, "RecVertexUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::VertexPacker>, "VertexUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::TwoProngVertexPacker>, "TwoProngVertexUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RichPIDPacker>, "RichPIDUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::MuonPIDPacker>, "MuonPIDUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::ParticlePacker>, "ParticleUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::TrackPacker>, "TrackUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::FlavourTagPacker>, "FlavourTagUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloHypoPacker>, "CaloHypoUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloClusterPacker>, "CaloClusterUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloDigitPacker>, "CaloDigitUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloAdcPacker>, "CaloAdcUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::WeightsVectorPacker>, "WeightsVectorUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RecSummaryPacker>, "RecSummaryUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::ProtoParticlePacker>, "ProtoParticleUnpacker" )
+
+  // SOA unpackers
+  DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::v3::Tracks>, "SOATrackUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::Calo::v2::Clusters>, "SOACaloClusterUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::Calo::v2::Hypotheses>, "SOACaloHypoUnpacker" )
+
+  // Relation unpackers
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::ParticleRelation<LHCb::VertexBase>>, "P2VRelationUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::ParticleRelation<LHCb::MCParticle>>, "P2MCPRelationUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::P2IntRelation>, "P2IntRelationUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::P2InfoRelation>, "P2InfoRelationUnpacker" )
+  DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::PP2MCPRelation>, "PP2MCPRelationUnpacker" )
+
+  // unpacker which just unpacks everything it can find -- usefull for debugging, interactive (GaudiPython) browsing
+  // of the TES
+  struct UnpackDstDataBank final : UnpackBase {
+    using UnpackBase::UnpackBase;
+    void operator()( LHCb::Hlt::PackedData::MappedInBuffers const& buffers ) const override {
+      auto loader = loader_for( buffers );
+      for ( const auto& [id, _] : buffers ) { // TODO: add MappedInBuffers.keys() to return a (lazy) range of keys...
+        auto r = loader.load( id );
+        if ( !r ) {
+          warning() << r.error() << endmsg;
+        } else if ( msgLevel( MSG::DEBUG ) ) {
+          debug() << "unpacked " << r->first << endmsg;
+        }
+      }
+    }
+  };
+  DECLARE_COMPONENT_WITH_ID( UnpackDstDataBank, "UnpackDstDataBank" )
+} // namespace DataPacking::Buffer
diff --git a/Event/EventPacker/src/component/RelationPackers.cpp b/Event/EventPacker/src/component/RelationPackers.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..573befe66c6058bba03f069f3ac43e0b2efe5b1e
--- /dev/null
+++ b/Event/EventPacker/src/component/RelationPackers.cpp
@@ -0,0 +1,140 @@
+/*****************************************************************************\
+* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration           *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#include "RelationPackers.h"
+
+namespace LHCb::Packers {
+
+  void P2InfoRelation::pack( const Relation1D<LHCb::Particle, LHCb::RelatedInfoMap>& rels,
+                             PackedRelatedInfoRelations&                             prels ) const {
+
+    // Make a entry in the containers vector, for this TES location
+    prels.containers().emplace_back();
+    auto& pcont = prels.containers().back();
+
+    // reference to original container and key
+    pcont.reference = StandardPacker::reference64( &prels, &rels, 0 );
+
+    // First entry in the relations vector
+    pcont.first = prels.data().size();
+
+    // Loop over the relations and fill
+    prels.data().reserve( prels.data().size() + rels.relations().size() );
+
+    // Use the packer to pack this location ...
+    m_rInfoPacker.pack( rels, prels );
+
+    // last entry in the relations vector
+    pcont.last = prels.data().size();
+  }
+
+  void P2InfoRelation::unpack( const PackedRelatedInfoRelations&     prels,
+                               Relation1D<Particle, RelatedInfoMap>& rels ) const {
+    auto resolver = details::Resolver{prels.linkMgr()};
+    for ( const auto& prel : prels.containers() ) {
+      for ( const auto& rel : LHCb::Packer::subrange( prels.relations(), prel.first, prel.last ) ) {
+
+        auto f = resolver.object<details::FromContainer<DataVector>>( rel.reference );
+        if ( !f ) {
+          parent().debug() << f.error() << " while retrieving object with key " << resolver.key( rel.reference )
+                           << " from " << resolver.path( rel.reference ) << endmsg;
+          continue;
+        }
+
+        LHCb::RelatedInfoMap t;
+        t.reserve( rel.last - rel.first );
+        for ( const auto& jj : LHCb::Packer::subrange( prels.info(), rel.first, rel.last ) ) { t.insert( jj ); }
+
+        StatusCode sc = rels.relate( f.value(), t );
+        if ( !sc )
+          parent().warning() << "Something went wrong with relation unpacking "
+                             << "sourceKey " << resolver.key( rel.reference ) << " sourceLink "
+                             << resolver.path( rel.reference ) << endmsg;
+      }
+    }
+    if ( resolver.hasErrors() ) resolver.dump( parent().warning() );
+    rels.i_sort();
+  }
+
+  void P2IntRelation::pack( const Relation1D<LHCb::Particle, int>& rels, PackedRelations& prels ) const {
+
+    // Make a new packed data object and save
+    auto& prel = prels.data().emplace_back();
+
+    // reference to original container
+    prel.container = StandardPacker::reference64( &prels, &rels, 0 );
+
+    // First object
+    prel.start = prels.sources().size();
+
+    // reserve size
+    const auto newSize = prels.sources().size() + rels.relations().size();
+    prels.sources().reserve( newSize );
+    prels.dests().reserve( newSize );
+
+    // Loop over relations
+    for ( const auto& R : rels.relations() ) {
+      prels.sources().emplace_back( StandardPacker::reference64( &prels, R.from() ) );
+      prels.dests().emplace_back( R.to() );
+    }
+
+    // last object
+    prel.end = prels.sources().size();
+  }
+
+  void P2IntRelation::unpack( const PackedRelations& prels, Relation1D<LHCb::Particle, int>& rels ) const {
+    auto resolver = details::Resolver{prels.linkMgr()};
+    for ( const auto& prel : prels.data() ) {
+      for ( int kk = prel.start; kk < prel.end; ++kk ) {
+        const auto& src = prels.sources()[kk];
+        const auto& dst = prels.dests()[kk];
+
+        const auto f = resolver.object<details::FromContainer<DataVector>>( src );
+        if ( !f ) {
+          if ( parent().msgLevel( MSG::DEBUG ) )
+            parent().debug() << f.error() << " while retrieving object with key " << resolver.key( src ) << " from "
+                             << resolver.path( src ) << endmsg;
+          continue;
+        }
+
+        StatusCode sc = rels.relate( f.value(), static_cast<int>( dst ) );
+        if ( !sc )
+          parent().warning() << "Something went wrong with relation unpacking "
+                             << "sourceKey " << resolver.key( src ) << " sourceLink " << resolver.path( src ) << endmsg;
+      }
+    }
+    if ( resolver.hasErrors() ) resolver.dump( parent().warning() );
+    rels.i_sort();
+  }
+
+} // namespace LHCb::Packers
+
+namespace LHCb {
+
+  // known unpacking transformations
+  void unpack( Gaudi::Algorithm const* parent, PackedWeightedRelations const& in,
+               RelationWeighted1D<ProtoParticle, MCParticle, double>& out ) {
+    Packers::WeightedRelation<ProtoParticle, MCParticle>{parent}.unpack( in, out );
+  }
+  void unpack( Gaudi::Algorithm const* parent, PackedRelatedInfoRelations const& in,
+               Relation1D<Particle, RelatedInfoMap>& out ) {
+    Packers::P2InfoRelation{parent}.unpack( in, out );
+  }
+  void unpack( Gaudi::Algorithm const* parent, PackedRelations const& in, Relation1D<Particle, VertexBase>& out ) {
+    Packers::ParticleRelation<VertexBase>{parent}.unpack( in, out );
+  }
+  void unpack( Gaudi::Algorithm const* parent, PackedRelations const& in, Relation1D<Particle, MCParticle>& out ) {
+    Packers::ParticleRelation<MCParticle>{parent}.unpack( in, out );
+  }
+  void unpack( Gaudi::Algorithm const* parent, PackedRelations const& in, Relation1D<Particle, int>& out ) {
+    Packers::P2IntRelation{parent}.unpack( in, out );
+  }
+
+} // namespace LHCb
diff --git a/Event/EventPacker/src/component/RelationPackers.h b/Event/EventPacker/src/component/RelationPackers.h
index dd95e3b3b75a3d22913fe88e476d6beff50a5bf6..c09c49b9f52f7613be833aec334091e0fd71ce30 100644
--- a/Event/EventPacker/src/component/RelationPackers.h
+++ b/Event/EventPacker/src/component/RelationPackers.h
@@ -11,6 +11,7 @@
 #pragma once
 #include "ErrorCategory.h"
 #include "Event/MCParticle.h"
+#include "Event/PackedEventChecks.h"
 #include "Event/PackedPartToRelatedInfoRelation.h"
 #include "Event/PackedRelations.h"
 #include "Event/PackedSharedObjectsContainer.h"
@@ -259,31 +260,7 @@ namespace LHCb::Packers {
     using DataVector       = LHCb::Relation1D<LHCb::Particle, int>;
     static const char* propertyName() { return "P2IntRelations"; }
 
-    void unpack( const PackedDataVector& prels, DataVector rels ) const {
-      auto resolver = details::Resolver{prels.linkMgr()};
-      for ( const auto& prel : prels.data() ) {
-        for ( int kk = prel.start; kk < prel.end; ++kk ) {
-          const auto& src = prels.sources()[kk];
-          const auto& dst = prels.dests()[kk];
-
-          const auto f = resolver.object<details::FromContainer<DataVector>>( src );
-          if ( !f ) {
-            if ( parent().msgLevel( MSG::DEBUG ) )
-              parent().debug() << f.error() << " while retrieving object with key " << resolver.key( src ) << " from "
-                               << resolver.path( src ) << endmsg;
-            continue;
-          }
-
-          StatusCode sc = rels.relate( f.value(), static_cast<int>( dst ) );
-          if ( !sc )
-            parent().warning() << "Something went wrong with relation unpacking "
-                               << "sourceKey " << resolver.key( src ) << " sourceLink " << resolver.path( src )
-                               << endmsg;
-        }
-      }
-      if ( resolver.hasErrors() ) resolver.dump( parent().warning() );
-      rels.i_sort();
-    }
+    void unpack( const PackedDataVector& prels, DataVector& rels ) const;
 
     template <typename Range>
     StatusCode check( const Range& dataA, const DataVector& dataB ) const {
@@ -322,31 +299,7 @@ namespace LHCb::Packers {
       return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
     }
 
-    void pack( const DataVector& rels, PackedDataVector& prels ) const {
-
-      // Make a new packed data object and save
-      auto& prel = prels.data().emplace_back();
-
-      // reference to original container
-      prel.container = StandardPacker::reference64( &prels, &rels, 0 );
-
-      // First object
-      prel.start = prels.sources().size();
-
-      // reserve size
-      const auto newSize = prels.sources().size() + rels.relations().size();
-      prels.sources().reserve( newSize );
-      prels.dests().reserve( newSize );
-
-      // Loop over relations
-      for ( const auto& R : rels.relations() ) {
-        prels.sources().emplace_back( StandardPacker::reference64( &prels, R.from() ) );
-        prels.dests().emplace_back( R.to() );
-      }
-
-      // last object
-      prel.end = prels.sources().size();
-    }
+    void pack( const DataVector& rels, PackedDataVector& prels ) const;
   };
 
   // Pack Proto particle 2 MC particle Relation
@@ -449,32 +402,7 @@ namespace LHCb::Packers {
     using PackedDataVector = LHCb::PackedRelatedInfoRelations;
     static const char* propertyName() { return "P2InfoRelations"; }
 
-    void unpack( const PackedDataVector& prels, DataVector& rels ) const {
-      auto resolver = details::Resolver{prels.linkMgr()};
-      for ( const auto& prel : prels.containers() ) {
-        for ( const auto& rel : LHCb::Packer::subrange( prels.relations(), prel.first, prel.last ) ) {
-
-          auto f = resolver.object<details::FromContainer<DataVector>>( rel.reference );
-          if ( !f ) {
-            parent().debug() << f.error() << " while retrieving object with key " << resolver.key( rel.reference )
-                             << " from " << resolver.path( rel.reference ) << endmsg;
-            continue;
-          }
-
-          LHCb::RelatedInfoMap t;
-          t.reserve( rel.last - rel.first );
-          for ( const auto& jj : LHCb::Packer::subrange( prels.info(), rel.first, rel.last ) ) { t.insert( jj ); }
-
-          StatusCode sc = rels.relate( f.value(), t );
-          if ( !sc )
-            parent().warning() << "Something went wrong with relation unpacking "
-                               << "sourceKey " << resolver.key( rel.reference ) << " sourceLink "
-                               << resolver.path( rel.reference ) << endmsg;
-        }
-      }
-      if ( resolver.hasErrors() ) resolver.dump( parent().warning() );
-      rels.i_sort();
-    }
+    void unpack( const PackedDataVector& prels, DataVector& rels ) const;
 
     template <typename Range>
     StatusCode check( const Range& dataA, const DataVector& dataB ) const {
@@ -513,27 +441,7 @@ namespace LHCb::Packers {
       return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
     }
 
-    void pack( const DataVector& rels, PackedDataVector& prels ) const {
-
-      // Make a entry in the containers vector, for this TES location
-      prels.containers().emplace_back();
-      auto& pcont = prels.containers().back();
-
-      // reference to original container and key
-      pcont.reference = StandardPacker::reference64( &prels, &rels, 0 );
-
-      // First entry in the relations vector
-      pcont.first = prels.data().size();
-
-      // Loop over the relations and fill
-      prels.data().reserve( prels.data().size() + rels.relations().size() );
-
-      // Use the packer to pack this location ...
-      m_rInfoPacker.pack( rels, prels );
-
-      // last entry in the relations vector
-      pcont.last = prels.data().size();
-    }
+    void pack( const DataVector& rels, PackedDataVector& prels ) const;
   };
 
   template <typename ValueType>
@@ -577,3 +485,15 @@ namespace LHCb::Packers {
   };
 
 } // namespace LHCb::Packers
+
+namespace LHCb {
+
+  // known unpacking transformations
+  void unpack( Gaudi::Algorithm const*, PackedWeightedRelations const&,
+               RelationWeighted1D<ProtoParticle, MCParticle, double>& );
+  void unpack( Gaudi::Algorithm const*, PackedRelatedInfoRelations const&, Relation1D<Particle, RelatedInfoMap>& );
+  void unpack( Gaudi::Algorithm const*, PackedRelations const&, Relation1D<Particle, VertexBase>& );
+  void unpack( Gaudi::Algorithm const*, PackedRelations const&, Relation1D<Particle, MCParticle>& );
+  void unpack( Gaudi::Algorithm const*, PackedRelations const&, Relation1D<Particle, int>& );
+
+} // namespace LHCb
diff --git a/Event/EventPacker/src/component/SelectivePacker.cpp b/Event/EventPacker/src/component/SelectivePacker.cpp
index 462b540b0869ab86fe0c9d9ee5969a228ed0c34b..a7cdaca24654c084a32afcd90e882ccdd1a263bd 100644
--- a/Event/EventPacker/src/component/SelectivePacker.cpp
+++ b/Event/EventPacker/src/component/SelectivePacker.cpp
@@ -8,7 +8,6 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#include "Traits.h"
 #include "BufferSOAPackerBaseAlg.h"
 #include "Event/HltDecReports.h"
 #include "Event/PackedData.h"
@@ -20,6 +19,7 @@
 #include "Kernel/IIndexedANNSvc.h"
 #include "Kernel/TaggedBool.h"
 #include "RegistryWrapper.h"
+#include "Traits.h"
 #include <LHCbAlgs/MergingTransformer.h>
 #include <algorithm>
 #include <cassert>
@@ -171,7 +171,6 @@ namespace LHCb {
   namespace {
     namespace Traits = Packers::Traits;
 
-
     const Gaudi::StringKey PackedObjectLocations{"PackedObjectLocations"};
 
     using Buffer = Hlt::PackedData::PackedDataOutBuffer;
diff --git a/Event/EventPacker/src/component/Traits.h b/Event/EventPacker/src/component/Traits.h
index c9603ff5b722d66317b711d8e119d0190bea62f1..282d813ea4842a7cc2bfefccb34ebe5ca06b6483 100644
--- a/Event/EventPacker/src/component/Traits.h
+++ b/Event/EventPacker/src/component/Traits.h
@@ -1,230 +1,241 @@
-#include <type_traits>
-#include "GaudiKernel/SharedObjectsContainer.h"
-#include "GaudiKernel/detected.h"
-#include "Event/PackedVertex.h"
-#include "Event/PackedRecVertex.h"
-#include "Event/PackedTwoProngVertex.h"
-#include "Event/PackedRichPID.h"
-#include "Event/PackedMuonPID.h"
-#include "Event/PackedProtoParticle.h"
-#include "Event/PackedParticle.h"
-#include "Event/PackedTrack.h"
-#include "Event/PackedFlavourTag.h"
-#include "Event/PackedCaloHypo.h"
-#include "Event/PackedCaloCluster.h"
-#include "Event/PackedCaloDigit.h"
-#include "Event/PackedCaloAdc.h"
-#include "Event/PackedWeightsVector.h"
-#include "Event/PackedRecSummary.h"
-#include "Event/PackedRelations.h"
-#include "Event/PackedPartToRelatedInfoRelation.h"
-#include "Relations/Relation1D.h"
-#include "Relations/RelationWeighted1D.h"
+/*****************************************************************************\
+* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration           *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
 #include "Event/CaloAdc.h"
 #include "Event/CaloCluster.h"
 #include "Event/CaloClusters_v2.h"
 #include "Event/CaloHypos_v2.h"
 #include "Event/FlavourTag.h"
 #include "Event/MCParticle.h"
+#include "Event/PackedCaloAdc.h"
+#include "Event/PackedCaloCluster.h"
+#include "Event/PackedCaloDigit.h"
+#include "Event/PackedCaloHypo.h"
+#include "Event/PackedFlavourTag.h"
+#include "Event/PackedMuonPID.h"
+#include "Event/PackedPartToRelatedInfoRelation.h"
+#include "Event/PackedParticle.h"
+#include "Event/PackedProtoParticle.h"
+#include "Event/PackedRecSummary.h"
+#include "Event/PackedRecVertex.h"
+#include "Event/PackedRelations.h"
+#include "Event/PackedRichPID.h"
+#include "Event/PackedTrack.h"
+#include "Event/PackedTwoProngVertex.h"
+#include "Event/PackedVertex.h"
+#include "Event/PackedWeightsVector.h"
 #include "Event/Particle.h"
 #include "Event/RecSummary.h"
 #include "Event/RelatedInfoMap.h"
 #include "Event/Track_v3.h"
 #include "Event/TwoProngVertex.h"
 #include "Event/WeightsVector.h"
+#include "GaudiKernel/SharedObjectsContainer.h"
+#include "GaudiKernel/detected.h"
 #include "RelationPackers.h"
+#include "Relations/Relation1D.h"
+#include "Relations/RelationWeighted1D.h"
+#include <type_traits>
 
 namespace LHCb::Packers::Traits {
-      namespace details {
-
-        template <typename T>
-        struct is_selection : std::false_type {};
-        template <typename T>
-        struct is_selection<SharedObjectsContainer<T>> : std::true_type {};
-
-        template <typename, typename = void>
-        struct remove_void_helper;
-
-        template <template <typename...> typename Tuple, typename... Ts>
-        struct remove_void_helper<Tuple<>, Tuple<Ts...>> {
-          using type = Tuple<Ts...>;
-        };
-
-        template <template <typename...> typename Tuple, typename Head, typename... Ts, typename... Us>
-        struct remove_void_helper<Tuple<Head, Ts...>, Tuple<Us...>> {
-          using type =
-              std::conditional_t<std::is_void_v<Head>, typename remove_void_helper<Tuple<Ts...>, Tuple<Us...>>::type,
-                                 typename remove_void_helper<Tuple<Ts...>, Tuple<Us..., Head>>::type>;
-        };
-
-        template <template <typename...> typename Tuple, typename... Ts>
-        struct remove_void_helper<Tuple<Ts...>> {
-          using type = typename remove_void_helper<Tuple<Ts...>, Tuple<>>::type;
-        };
-
-        template <typename T>
-        using remove_void = typename remove_void_helper<T>::type;
-
-        template <template <typename...> typename T, template <typename> typename F, typename... Ts>
-        using apply_helper = T<F<Ts>...>; // TODO: check whether F<Ts> is valid -- if not, skip
-
-        template <typename T>
-        using Container_t = typename T::Container;
-        template <typename T>
-        using Selection_t = typename T::Selection;
-        template <typename T>
-        using Contained_t = typename T::contained_type;
-        template <typename T>
-        using Entry_t = typename T::Entry; // KeyedContainer has 'contained_type', relations have 'Entry'...
-
-        template <typename D, typename P>
-        struct packer_mapping {
-          using Data      = D;
-          using Packer    = P;
-          using Container = Gaudi::cpp17::detected_or_t<typename Packer::DataVector, Container_t, D>;
-          using Selection = Gaudi::cpp17::detected_or_t<void, Selection_t, D>;
-          static_assert( std::is_same_v<Container, typename Packer::DataVector> );
-        };
-
-        template <typename>
-        struct Info_for_;
-        template <>
-        struct Info_for_<RecVertex> : packer_mapping<RecVertex, RecVertexPacker> {};
-        template <>
-        struct Info_for_<Vertex> : packer_mapping<Vertex, VertexPacker> {};
-        template <>
-        struct Info_for_<TwoProngVertex> : packer_mapping<TwoProngVertex, TwoProngVertexPacker> {};
-        template <>
-        struct Info_for_<RichPID> : packer_mapping<RichPID, RichPIDPacker> {};
-        template <>
-        struct Info_for_<MuonPID> : packer_mapping<MuonPID, MuonPIDPacker> {};
-        template <>
-        struct Info_for_<ProtoParticle> : packer_mapping<ProtoParticle, ProtoParticlePacker> {};
-        template <>
-        struct Info_for_<Particle> : packer_mapping<Particle, ParticlePacker> {};
-        template <>
-        struct Info_for_<Track> : packer_mapping<Track, TrackPacker> {};
-        template <>
-        struct Info_for_<FlavourTag> : packer_mapping<FlavourTag, FlavourTagPacker> {};
-        template <>
-        struct Info_for_<CaloHypo> : packer_mapping<CaloHypo, CaloHypoPacker> {};
-        template <>
-        struct Info_for_<CaloCluster> : packer_mapping<CaloCluster, CaloClusterPacker> {};
-        template <>
-        struct Info_for_<CaloDigit> : packer_mapping<CaloDigit, CaloDigitPacker> {};
-        template <>
-        struct Info_for_<CaloAdc> : packer_mapping<CaloAdc, CaloAdcPacker> {};
-        template <>
-        struct Info_for_<WeightsVector> : packer_mapping<WeightsVector, WeightsVectorPacker> {};
-        template <>
-        struct Info_for_<RecSummary> : packer_mapping<RecSummary, RecSummaryPacker> {};
-        template <>
-        struct Info_for_<typename Relation1D<Particle, VertexBase>::Entry>
-            : packer_mapping<typename Relation1D<Particle, VertexBase>::Entry, Packers::ParticleRelation<VertexBase>> {
-        };
-        template <>
-        struct Info_for_<typename Relation1D<Particle, MCParticle>::Entry>
-            : packer_mapping<typename Relation1D<Particle, MCParticle>::Entry, Packers::ParticleRelation<MCParticle>> {
-        };
-        template <>
-        struct Info_for_<typename Relation1D<Particle, int>::Entry>
-            : packer_mapping<typename Relation1D<Particle, int>::Entry, Packers::P2IntRelation> {};
-        template <>
-        struct Info_for_<typename Relation1D<Particle, RelatedInfoMap>::Entry>
-            : packer_mapping<typename Relation1D<Particle, RelatedInfoMap>::Entry, Packers::P2InfoRelation> {};
-        template <>
-        struct Info_for_<typename LHCb::RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry>
-            : packer_mapping<typename LHCb::RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry,
-                             LHCb::Packers::PP2MCPRelation> {};
-      } // namespace details
-
-      template <typename T>
-      using contained_type =
-          Gaudi::cpp17::detected_or_t<Gaudi::cpp17::detected_or_t<T, details::Entry_t, T>, details::Contained_t, T>;
-
-      template <typename T>
-      using container = typename details::Info_for_<contained_type<T>>::Container;
-
-      template <typename T>
-      using selection = typename details::Info_for_<contained_type<T>>::Selection;
-
-      template <typename T>
-      using packer = typename details::Info_for_<contained_type<T>>::Packer;
-
-      template <typename T>
-      using id_ = T;
-
-      template <typename T>
-      const char* containerName() {
-        if constexpr ( details::is_selection<T>::value ) {
-          static const std::string s = std::string{packer<T>::propertyName()}.append( "Selection" );
-          return s.c_str();
-        } else {
-          return packer<T>::propertyName();
-        }
-      }
-
-      // relations are last, as we may want to prune entries where the 'from' side is not packed
-      // so anything appearing as 'from' must be known at that point
-      template <template <typename...> typename T, template <typename> typename Fun = id_>
-      using Expand =
-          details::apply_helper<T, Fun, RecVertex, Vertex, TwoProngVertex, RichPID, MuonPID, ProtoParticle, Particle,
-                                Track, FlavourTag, CaloHypo, CaloCluster, CaloDigit, CaloAdc, WeightsVector, RecSummary,
-                                Relation1D<Particle, VertexBase>::Entry, Relation1D<Particle, MCParticle>::Entry,
-                                RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry,
-                                Relation1D<Particle, int>::Entry, Relation1D<Particle, RelatedInfoMap>::Entry>;
-
-      //  T<F<Ts>...>, but with the
-      //  is_void_v<F<Ts>> cases removed
-      // TODO: remove the 'void' bit in F<Ts>, and just pick the ones for which F<Ts> is valid...
-      template <template <typename...> typename T, template <typename> typename Fun = id_>
-      using Gather = details::remove_void<Expand<T, Fun>>;
-
-}
+  namespace details {
+
+    template <typename T>
+    struct is_selection : std::false_type {};
+    template <typename T>
+    struct is_selection<SharedObjectsContainer<T>> : std::true_type {};
+
+    template <typename, typename = void>
+    struct remove_void_helper;
+
+    template <template <typename...> typename Tuple, typename... Ts>
+    struct remove_void_helper<Tuple<>, Tuple<Ts...>> {
+      using type = Tuple<Ts...>;
+    };
+
+    template <template <typename...> typename Tuple, typename Head, typename... Ts, typename... Us>
+    struct remove_void_helper<Tuple<Head, Ts...>, Tuple<Us...>> {
+      using type =
+          std::conditional_t<std::is_void_v<Head>, typename remove_void_helper<Tuple<Ts...>, Tuple<Us...>>::type,
+                             typename remove_void_helper<Tuple<Ts...>, Tuple<Us..., Head>>::type>;
+    };
+
+    template <template <typename...> typename Tuple, typename... Ts>
+    struct remove_void_helper<Tuple<Ts...>> {
+      using type = typename remove_void_helper<Tuple<Ts...>, Tuple<>>::type;
+    };
+
+    template <typename T>
+    using remove_void = typename remove_void_helper<T>::type;
+
+    template <template <typename...> typename T, template <typename> typename F, typename... Ts>
+    using apply_helper = T<F<Ts>...>; // TODO: check whether F<Ts> is valid -- if not, skip
+
+    template <typename T>
+    using Container_t = typename T::Container;
+    template <typename T>
+    using Selection_t = typename T::Selection;
+    template <typename T>
+    using Contained_t = typename T::contained_type;
+    template <typename T>
+    using Entry_t = typename T::Entry; // KeyedContainer has 'contained_type', relations have 'Entry'...
+
+    template <typename D, typename P>
+    struct packer_mapping {
+      using Data            = D;
+      using Packer          = P;
+      using Container       = Gaudi::cpp17::detected_or_t<typename Packer::DataVector, Container_t, D>;
+      using PackedContainer = typename Packer::PackedDataVector;
+      using Selection       = Gaudi::cpp17::detected_or_t<void, Selection_t, D>;
+      static_assert( std::is_same_v<Container, typename Packer::DataVector> );
+    };
+
+    template <typename>
+    struct Info_for_;
+    template <>
+    struct Info_for_<RecVertex> : packer_mapping<RecVertex, RecVertexPacker> {};
+    template <>
+    struct Info_for_<Vertex> : packer_mapping<Vertex, VertexPacker> {};
+    template <>
+    struct Info_for_<TwoProngVertex> : packer_mapping<TwoProngVertex, TwoProngVertexPacker> {};
+    template <>
+    struct Info_for_<RichPID> : packer_mapping<RichPID, RichPIDPacker> {};
+    template <>
+    struct Info_for_<MuonPID> : packer_mapping<MuonPID, MuonPIDPacker> {};
+    template <>
+    struct Info_for_<ProtoParticle> : packer_mapping<ProtoParticle, ProtoParticlePacker> {};
+    template <>
+    struct Info_for_<Particle> : packer_mapping<Particle, ParticlePacker> {};
+    template <>
+    struct Info_for_<Track> : packer_mapping<Track, TrackPacker> {};
+    template <>
+    struct Info_for_<FlavourTag> : packer_mapping<FlavourTag, FlavourTagPacker> {};
+    template <>
+    struct Info_for_<CaloHypo> : packer_mapping<CaloHypo, CaloHypoPacker> {};
+    template <>
+    struct Info_for_<CaloCluster> : packer_mapping<CaloCluster, CaloClusterPacker> {};
+    template <>
+    struct Info_for_<CaloDigit> : packer_mapping<CaloDigit, CaloDigitPacker> {};
+    template <>
+    struct Info_for_<CaloAdc> : packer_mapping<CaloAdc, CaloAdcPacker> {};
+    template <>
+    struct Info_for_<WeightsVector> : packer_mapping<WeightsVector, WeightsVectorPacker> {};
+    template <>
+    struct Info_for_<RecSummary> : packer_mapping<RecSummary, RecSummaryPacker> {};
+    template <>
+    struct Info_for_<typename Relation1D<Particle, VertexBase>::Entry>
+        : packer_mapping<typename Relation1D<Particle, VertexBase>::Entry, Packers::ParticleRelation<VertexBase>> {};
+    template <>
+    struct Info_for_<typename Relation1D<Particle, MCParticle>::Entry>
+        : packer_mapping<typename Relation1D<Particle, MCParticle>::Entry, Packers::ParticleRelation<MCParticle>> {};
+    template <>
+    struct Info_for_<typename Relation1D<Particle, int>::Entry>
+        : packer_mapping<typename Relation1D<Particle, int>::Entry, Packers::P2IntRelation> {};
+    template <>
+    struct Info_for_<typename Relation1D<Particle, RelatedInfoMap>::Entry>
+        : packer_mapping<typename Relation1D<Particle, RelatedInfoMap>::Entry, Packers::P2InfoRelation> {};
+    template <>
+    struct Info_for_<typename LHCb::RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry>
+        : packer_mapping<typename LHCb::RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry,
+                         LHCb::Packers::PP2MCPRelation> {};
+  } // namespace details
+
+  template <typename T>
+  using contained_type =
+      Gaudi::cpp17::detected_or_t<Gaudi::cpp17::detected_or_t<T, details::Entry_t, T>, details::Contained_t, T>;
+
+  template <typename T>
+  using container = typename details::Info_for_<contained_type<T>>::Container;
+
+  template <typename T>
+  using packed_container = typename details::Info_for_<contained_type<T>>::PackedContainer;
+
+  template <typename T>
+  using selection = typename details::Info_for_<contained_type<T>>::Selection;
+
+  template <typename T>
+  using packer = typename details::Info_for_<contained_type<T>>::Packer;
+
+  template <typename T>
+  using id_ = T;
+
+  template <typename T>
+  const char* containerName() {
+    if constexpr ( details::is_selection<T>::value ) {
+      static const std::string s = std::string{packer<T>::propertyName()}.append( "Selection" );
+      return s.c_str();
+    } else {
+      return packer<T>::propertyName();
+    }
+  }
+
+  // relations are last, as we may want to prune entries where the 'from' side is not packed
+  // so anything appearing as 'from' must be known at that point
+  template <template <typename...> typename T, template <typename> typename Fun = id_>
+  using Expand =
+      details::apply_helper<T, Fun, RecVertex, Vertex, TwoProngVertex, RichPID, MuonPID, ProtoParticle, Particle, Track,
+                            FlavourTag, CaloHypo, CaloCluster, CaloDigit, CaloAdc, WeightsVector, RecSummary,
+                            Relation1D<Particle, VertexBase>::Entry, Relation1D<Particle, MCParticle>::Entry,
+                            RelationWeighted1D<ProtoParticle, MCParticle, double>::Entry,
+                            Relation1D<Particle, int>::Entry, Relation1D<Particle, RelatedInfoMap>::Entry>;
+
+  //  T<F<Ts>...>, but with the
+  //  is_void_v<F<Ts>> cases removed
+  // TODO: remove the 'void' bit in F<Ts>, and just pick the ones for which F<Ts> is valid...
+  template <template <typename...> typename T, template <typename> typename Fun = id_>
+  using Gather = details::remove_void<Expand<T, Fun>>;
+
+} // namespace LHCb::Packers::Traits
 
 namespace LHCb::Packers::Traits {
 
-      template <typename... Ts>
-      struct TypeList;
+  template <typename... Ts>
+  struct TypeList;
 
-      template <typename TL1, typename TL2>
-      struct concat;
+  template <typename TL1, typename TL2>
+  struct concat;
 
-      template <typename... Ts, typename... Us>
-      struct concat<TypeList<Ts...>, TypeList<Us...>> {
-        using type = TypeList<Ts..., Us...>;
-      };
+  template <typename... Ts, typename... Us>
+  struct concat<TypeList<Ts...>, TypeList<Us...>> {
+    using type = TypeList<Ts..., Us...>;
+  };
 
-      template <typename TL1, typename TL2>
-      using concat_t = typename concat<TL1, TL2>::type;
+  template <typename TL1, typename TL2>
+  using concat_t = typename concat<TL1, TL2>::type;
 
-      template <template <typename...> typename F, typename T>
-      struct distribute_helper;
+  template <template <typename...> typename F, typename T>
+  struct distribute_helper;
 
-      template <template <typename...> typename F, typename... Ts>
-      struct distribute_helper<F, TypeList<Ts...>> {
-        using type = F<Ts...>;
-      };
+  template <template <typename...> typename F, typename... Ts>
+  struct distribute_helper<F, TypeList<Ts...>> {
+    using type = F<Ts...>;
+  };
 
-      template <template <typename...> typename F, typename TL>
-      using distribute_t = typename distribute_helper<F, TL>::type;
+  template <template <typename...> typename F, typename TL>
+  using distribute_t = typename distribute_helper<F, TL>::type;
 
-      using SelectionTypes = Gather<TypeList, Traits::selection>;
-      using ContainerTypes = Gather<TypeList, Traits::container>;
+  using SelectionTypes = Gather<TypeList, Traits::selection>;
+  using ContainerTypes = Gather<TypeList, Traits::container>;
 
-      using input_t = distribute_t<std::tuple, concat_t<SelectionTypes, ContainerTypes>>;
+  using input_t = distribute_t<std::tuple, concat_t<SelectionTypes, ContainerTypes>>;
 
-      static_assert(
-          std::is_same_v<
-              input_t,
-              std::tuple<RecVertex::Selection, Vertex::Selection, TwoProngVertex::Selection, Particle::Selection,
-                         Track::Selection, FlavourTag::Selection, CaloHypo::Selection, CaloCluster::Selection,
-                         RecVertex::Container, Vertex::Container, TwoProngVertex::Container, RichPID::Container,
-                         MuonPID::Container, ProtoParticle::Container, Particle::Container, Track::Container,
-                         FlavourTag::Container, CaloHypo::Container, CaloCluster::Container, CaloDigit::Container,
-                         CaloAdc::Container, WeightsVector::Container, RecSummary, Relation1D<Particle, VertexBase>,
-                         Relation1D<Particle, MCParticle>, RelationWeighted1D<ProtoParticle, MCParticle, double>,
-                         Relation1D<Particle, int>, Relation1D<Particle, RelatedInfoMap>>> );
+  static_assert( std::is_same_v<
+                 input_t,
+                 std::tuple<RecVertex::Selection, Vertex::Selection, TwoProngVertex::Selection, Particle::Selection,
+                            Track::Selection, FlavourTag::Selection, CaloHypo::Selection, CaloCluster::Selection,
+                            RecVertex::Container, Vertex::Container, TwoProngVertex::Container, RichPID::Container,
+                            MuonPID::Container, ProtoParticle::Container, Particle::Container, Track::Container,
+                            FlavourTag::Container, CaloHypo::Container, CaloCluster::Container, CaloDigit::Container,
+                            CaloAdc::Container, WeightsVector::Container, RecSummary, Relation1D<Particle, VertexBase>,
+                            Relation1D<Particle, MCParticle>, RelationWeighted1D<ProtoParticle, MCParticle, double>,
+                            Relation1D<Particle, int>, Relation1D<Particle, RelatedInfoMap>>> );
 
 #if 0
 template <typename T>
@@ -238,4 +249,4 @@ int fun() {
 static int iiii = fun<input_t>();
 #endif
 
-}
+} // namespace LHCb::Packers::Traits
diff --git a/Event/EventPacker/src/component/Unpackers.cpp b/Event/EventPacker/src/component/Unpackers.cpp
index 301b5d655d4410b24eac6091028f3aa781802e1b..71924971398155f3171ab533331b4212fb9cf615 100644
--- a/Event/EventPacker/src/component/Unpackers.cpp
+++ b/Event/EventPacker/src/component/Unpackers.cpp
@@ -9,26 +9,12 @@
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
 
-#include "BufferSOAUnpackerBaseAlg.h"
-#include "BufferUnpackerBaseAlg.h"
-#include "RelationPackers.h"
 #include "UnpackerBaseAlg.h"
 
-#include "Event/PackedCaloAdc.h"
-#include "Event/PackedCaloCluster.h"
-#include "Event/PackedCaloDigit.h"
 #include "Event/PackedCaloHypo.h"
-#include "Event/PackedFlavourTag.h"
 #include "Event/PackedMuonPID.h"
-#include "Event/PackedPartToRelatedInfoRelation.h"
-#include "Event/PackedParticle.h"
-#include "Event/PackedProtoParticle.h"
-#include "Event/PackedRecSummary.h"
-#include "Event/PackedRecVertex.h"
-#include "Event/PackedRelations.h"
 #include "Event/PackedRichPID.h"
 #include "Event/PackedTrack.h"
-#include "Event/PackedTwoProngVertex.h"
 #include "Event/PackedVertex.h"
 #include "Event/PackedWeightsVector.h"
 
@@ -40,10 +26,6 @@
 #include "Event/PackedMCRichSegment.h"
 #include "Event/PackedMCRichTrack.h"
 
-#include "Event/CaloClusters_v2.h"
-#include "Event/CaloHypos_v2.h"
-#include "Event/Track_v3.h"
-
 namespace DataPacking {
   // MC Packers don't serialize data so we keep the ones taking packed objects
   DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::MCHitPacker>,
@@ -82,52 +64,4 @@ namespace DataPacking {
   DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::TrackPacker>, "UnpackTrack" )
   DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloHypoPacker>, "UnpackCaloHypo" )
 
-  namespace Buffer {
-    // These packers take one data buffer location and produce unpacked object
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RecVertexPacker>, "RecVertexUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::VertexPacker>, "VertexUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::TwoProngVertexPacker>, "TwoProngVertexUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RichPIDPacker>, "RichPIDUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::MuonPIDPacker>, "MuonPIDUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::ParticlePacker>, "ParticleUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::TrackPacker>, "TrackUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::FlavourTagPacker>, "FlavourTagUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloHypoPacker>, "CaloHypoUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloClusterPacker>, "CaloClusterUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloDigitPacker>, "CaloDigitUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::CaloAdcPacker>, "CaloAdcUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::WeightsVectorPacker>, "WeightsVectorUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::RecSummaryPacker>, "RecSummaryUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::ProtoParticlePacker>, "ProtoParticleUnpacker" )
-
-    // SOA unpackers
-    DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::v3::Tracks>, "SOATrackUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::Calo::v2::Clusters>, "SOACaloClusterUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( SOA::Unpack<LHCb::Event::Calo::v2::Hypotheses>, "SOACaloHypoUnpacker" )
-
-    // Relation unpackers
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::ParticleRelation<LHCb::VertexBase>>, "P2VRelationUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::ParticleRelation<LHCb::MCParticle>>, "P2MCPRelationUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::P2IntRelation>, "P2IntRelationUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::P2InfoRelation>, "P2InfoRelationUnpacker" )
-    DECLARE_COMPONENT_WITH_ID( Unpack<LHCb::Packers::PP2MCPRelation>, "PP2MCPRelationUnpacker" )
-
-    // unpacker which just unpacks everything it can find -- usefull for debugging, interactive (GaudiPython) browsing
-    // of the TES
-    struct UnpackDstDataBank final : UnpackBase {
-      using UnpackBase::UnpackBase;
-      void operator()( LHCb::Hlt::PackedData::MappedInBuffers const& buffers ) const override {
-        auto loader = loader_for( buffers );
-        for ( const auto& [id, _] : buffers ) { // TODO: add MappedInBuffers.keys() to return a (lazy) range of keys...
-          auto r = loader.load( id );
-          if ( !r ) {
-            warning() << r.error() << endmsg;
-          } else if ( msgLevel( MSG::DEBUG ) ) {
-            debug() << "unpacked " << r->first << endmsg;
-          }
-        }
-      }
-    };
-    DECLARE_COMPONENT_WITH_ID( UnpackDstDataBank, "UnpackDstDataBank" )
-  } // namespace Buffer
 } // namespace DataPacking
diff --git a/Event/EventPacker/src/lib/PackedCaloAdc.cpp b/Event/EventPacker/src/lib/PackedCaloAdc.cpp
index f89f35c427c92d1d29151a999fb58829997c3441..6a6987a94d928899b7d5175e69f242779d4c1591 100644
--- a/Event/EventPacker/src/lib/PackedCaloAdc.cpp
+++ b/Event/EventPacker/src/lib/PackedCaloAdc.cpp
@@ -61,3 +61,9 @@ StatusCode CaloAdcPacker::check( const Data* dataA, const Data* dataB ) const {
   }
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const PackedCaloAdcs& in, CaloAdcs& out ) {
+    CaloAdcPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedCaloCluster.cpp b/Event/EventPacker/src/lib/PackedCaloCluster.cpp
index 0594601be72a4db2523bf0a452808ebdabdb142a..14efbfdeff82ae6ade0e0e30ab8d9225213fb362 100644
--- a/Event/EventPacker/src/lib/PackedCaloCluster.cpp
+++ b/Event/EventPacker/src/lib/PackedCaloCluster.cpp
@@ -214,3 +214,10 @@ StatusCode CaloClusterPacker::check( const Data* dataA, const Data* dataB ) cons
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const CaloClusterPacker::PackedDataVector& in,
+               CaloClusterPacker::DataVector& out ) {
+    CaloClusterPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedCaloDigit.cpp b/Event/EventPacker/src/lib/PackedCaloDigit.cpp
index e4e55ac7fa1a603137e7cf9214bf914d794f510a..6daa890764c45ec8ba019eba73ebb849c56e4505 100644
--- a/Event/EventPacker/src/lib/PackedCaloDigit.cpp
+++ b/Event/EventPacker/src/lib/PackedCaloDigit.cpp
@@ -65,3 +65,10 @@ StatusCode CaloDigitPacker::check( const Data* dataA, const Data* dataB ) const
   }
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const CaloDigitPacker::PackedDataVector& in,
+               CaloDigitPacker::DataVector& out ) {
+    CaloDigitPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedCaloHypo.cpp b/Event/EventPacker/src/lib/PackedCaloHypo.cpp
index adc88f390324b8200544961555be2e6d61e28472..2ea640561e0b62f7b524b0941b77fcfe4e178a10 100644
--- a/Event/EventPacker/src/lib/PackedCaloHypo.cpp
+++ b/Event/EventPacker/src/lib/PackedCaloHypo.cpp
@@ -289,3 +289,10 @@ StatusCode CaloHypoPacker::check( const Data* oHypo, const Data* tHypo ) const {
   }
   return sc;
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const CaloHypoPacker::PackedDataVector& in,
+               CaloHypoPacker::DataVector& out ) {
+    CaloHypoPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedFlavourTag.cpp b/Event/EventPacker/src/lib/PackedFlavourTag.cpp
index 30e13c3684a34ebae3876620c552d87214dc8133..554a22b1ec0c96906664b982137cded020e7a346 100644
--- a/Event/EventPacker/src/lib/PackedFlavourTag.cpp
+++ b/Event/EventPacker/src/lib/PackedFlavourTag.cpp
@@ -196,3 +196,11 @@ StatusCode FlavourTagPacker::check( const Data* dataA, const Data* dataB ) const
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const FlavourTagPacker::PackedDataVector& in,
+               FlavourTagPacker::DataVector& out ) {
+    FlavourTagPacker{parent}.unpack( in, out );
+  }
+
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedMuonPID.cpp b/Event/EventPacker/src/lib/PackedMuonPID.cpp
index 10b64d7db7dcecfed1904e5a09edde4b55343aa1..bb71dad95c9ba428e6a02475caf742ad3d877719 100644
--- a/Event/EventPacker/src/lib/PackedMuonPID.cpp
+++ b/Event/EventPacker/src/lib/PackedMuonPID.cpp
@@ -132,4 +132,11 @@ StatusCode MuonPIDPacker::check( const Data* dataA, const Data* dataB ) const {
   }
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
-}
\ No newline at end of file
+}
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const MuonPIDPacker::PackedDataVector& in,
+               MuonPIDPacker::DataVector& out ) {
+    MuonPIDPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedPartToRelatedInfoRelation.cpp b/Event/EventPacker/src/lib/PackedPartToRelatedInfoRelation.cpp
index a302d384fb9d4ac00edd38b645928dc7b05e2bed..7699df87eb6e37f99613e6d35bf4bed95fe2abf5 100644
--- a/Event/EventPacker/src/lib/PackedPartToRelatedInfoRelation.cpp
+++ b/Event/EventPacker/src/lib/PackedPartToRelatedInfoRelation.cpp
@@ -144,3 +144,8 @@ StatusCode RelatedInfoRelationsPacker::check( const DataVector& dataA, const Dat
   // finally return
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+void unpack( Gaudi::Algorithm const* parent, const PackedRelatedInfoRelations& in,
+             Relation1D<Particle, RelatedInfoMap>& out ) {
+  RelatedInfoRelationsPacker{parent}.unpack( in, out );
+}
diff --git a/Event/EventPacker/src/lib/PackedParticle.cpp b/Event/EventPacker/src/lib/PackedParticle.cpp
index 735101c7f9d9563397cdfbd43723c5191b4a8c94..0b3a974e3a2a2c25ee87658c27f01707fc24f316 100644
--- a/Event/EventPacker/src/lib/PackedParticle.cpp
+++ b/Event/EventPacker/src/lib/PackedParticle.cpp
@@ -372,3 +372,9 @@ StatusCode ParticlePacker::check( const Data* dataA, const Data* dataB ) const {
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const PackedParticles& in, Particles& out ) {
+    ParticlePacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedProtoParticle.cpp b/Event/EventPacker/src/lib/PackedProtoParticle.cpp
index 77eb6e09b9f0062876eab33c184ca0c573f8262d..c3865fb098937c7bcb05a5d5bd8ec74cac4c7ea0 100644
--- a/Event/EventPacker/src/lib/PackedProtoParticle.cpp
+++ b/Event/EventPacker/src/lib/PackedProtoParticle.cpp
@@ -241,3 +241,10 @@ StatusCode ProtoParticlePacker::check( const Data* dataA, const Data* dataB ) co
 
   return ( isOK ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const ProtoParticlePacker::PackedDataVector& in,
+               ProtoParticlePacker::DataVector& out ) {
+    ProtoParticlePacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedRecSummary.cpp b/Event/EventPacker/src/lib/PackedRecSummary.cpp
index b4e243fd355a5f67128f9f0b5c531f031b8a8658..a52b3b5b93bb7677551c29cd1e53a2e96ac84300 100644
--- a/Event/EventPacker/src/lib/PackedRecSummary.cpp
+++ b/Event/EventPacker/src/lib/PackedRecSummary.cpp
@@ -35,3 +35,10 @@ void RecSummaryPacker::unpack( const PackedDataVector& psums, DataVector& sums )
 StatusCode RecSummaryPacker::check( const DataVector& dataA, const DataVector& dataB ) const {
   return ( dataA.summaryData() == dataB.summaryData() ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const RecSummaryPacker::PackedDataVector& in,
+               RecSummaryPacker::DataVector& out ) {
+    RecSummaryPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedRecVertex.cpp b/Event/EventPacker/src/lib/PackedRecVertex.cpp
index 62b48ccbc1e93de54eacfe7182369f0e15190942..d733066cc15624374acfe5db427026f00d11c7ff 100644
--- a/Event/EventPacker/src/lib/PackedRecVertex.cpp
+++ b/Event/EventPacker/src/lib/PackedRecVertex.cpp
@@ -177,3 +177,9 @@ StatusCode RecVertexPacker::check( const Data* dataA, const Data* dataB ) const
 
   return ( isOK ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const PackedRecVertices& in, RecVertices& out ) {
+    RecVertexPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedRichPID.cpp b/Event/EventPacker/src/lib/PackedRichPID.cpp
index d79aec87c9620da7115d459d4d4a8c5718afb1a2..397474c39a695450c553c92cb80ccc432692a61e 100644
--- a/Event/EventPacker/src/lib/PackedRichPID.cpp
+++ b/Event/EventPacker/src/lib/PackedRichPID.cpp
@@ -130,4 +130,11 @@ StatusCode RichPIDPacker::check( const Data* dataA, const Data* dataB ) const {
   }
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
-}
\ No newline at end of file
+}
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const RichPIDPacker::PackedDataVector& in,
+               RichPIDPacker::DataVector& out ) {
+    RichPIDPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedTrack.cpp b/Event/EventPacker/src/lib/PackedTrack.cpp
index a29b7f5624a8dbebadd4c53353bb7deb8fc3cfde..232a20dde754e6807f8bc98ff39f2df869ff932f 100644
--- a/Event/EventPacker/src/lib/PackedTrack.cpp
+++ b/Event/EventPacker/src/lib/PackedTrack.cpp
@@ -516,3 +516,9 @@ void TrackPacker::compareStates( const LHCb::State& oSta, const LHCb::State& tSt
     parent().info() << endmsg;
   }
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const TrackPacker::PackedDataVector& in, TrackPacker::DataVector& out ) {
+    TrackPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedTwoProngVertex.cpp b/Event/EventPacker/src/lib/PackedTwoProngVertex.cpp
index 32a8496e28f665a1e83cc399375ee958784d75df..8042edef090bc50cf15370e8cc37e3e1b637d1c8 100644
--- a/Event/EventPacker/src/lib/PackedTwoProngVertex.cpp
+++ b/Event/EventPacker/src/lib/PackedTwoProngVertex.cpp
@@ -309,3 +309,9 @@ StatusCode TwoProngVertexPacker::check( const Data* dataA, const Data* dataB ) c
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const PackedTwoProngVertices& in, TwoProngVertices& out ) {
+    TwoProngVertexPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedVertex.cpp b/Event/EventPacker/src/lib/PackedVertex.cpp
index 47b846a3456eb101d9f130fe37c8b4fe2e75ce5a..04ff1a1d395cde6bd87fd4fd07b1ef723e969da6 100644
--- a/Event/EventPacker/src/lib/PackedVertex.cpp
+++ b/Event/EventPacker/src/lib/PackedVertex.cpp
@@ -165,3 +165,10 @@ StatusCode VertexPacker::check( const Data* dataA, const Data* dataB ) const {
 
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+namespace LHCb {
+  void unpack( Gaudi::Algorithm const* parent, const VertexPacker::PackedDataVector& in,
+               VertexPacker::DataVector& out ) {
+    VertexPacker{parent}.unpack( in, out );
+  }
+} // namespace LHCb
diff --git a/Event/EventPacker/src/lib/PackedWeightsVector.cpp b/Event/EventPacker/src/lib/PackedWeightsVector.cpp
index 002f1198e61978e3fe5d842fde5404a4244d7c6b..aaf7e51c94b27b59c6c0c92af3031d93b195f012 100644
--- a/Event/EventPacker/src/lib/PackedWeightsVector.cpp
+++ b/Event/EventPacker/src/lib/PackedWeightsVector.cpp
@@ -66,3 +66,7 @@ StatusCode WeightsVectorPacker::check( const Data* dataA, const Data* dataB ) co
   // Return final status
   return ( ok ? StatusCode::SUCCESS : StatusCode::FAILURE );
 }
+
+void unpack( Gaudi::Algorithm const* parent, const PackedWeightsVector& in, WeightsVectors& out ) {
+  WeightsVectorPacker{parent}.unpack( in, out );
+}