diff --git a/Tracking/Acts/ActsConfig/python/ActsClusterizationConfig.py b/Tracking/Acts/ActsConfig/python/ActsClusterizationConfig.py
index 6b9916dd4b432b9e0701aef7668f642dd5baf1f9..f4aba186ccba1d11ae49efa01d15cb2787511f82 100644
--- a/Tracking/Acts/ActsConfig/python/ActsClusterizationConfig.py
+++ b/Tracking/Acts/ActsConfig/python/ActsClusterizationConfig.py
@@ -203,7 +203,7 @@ def ActsMainClusterizationCfg(flags,
                                                         name="ActsPixelClusterPreparationAlg",
                                                         RoIs=RoIs,
                                                         useCache=True,
-                                                        OutputCollection="ITkPixelClusters_InView",
+                                                        OutputCollection="ITkPixelClusters_Cached",
                                                         InputIDC="ActsPixelClustersCache"))
             
         if flags.Detector.EnableITkStrip:
@@ -211,7 +211,7 @@ def ActsMainClusterizationCfg(flags,
                                                         name="ActsStripClusterCachePreparationAlg",
                                                         RoIs=RoIs,
                                                         useCache=True,
-                                                        OutputCollection="ITkStripClusters_InView",
+                                                        OutputCollection="ITkStripClusters_Cached",
                                                         InputIDC="ActsStripClustersCache"))
             
     # Analysis extensions
@@ -231,8 +231,9 @@ def ActsConversionClusterizationCfg(flags) -> ComponentAccumulator:
     if flags.Acts.useCache:
         acc.merge(ActsStripClusterizationAlgCfg(flags,
                                                 name="ActsConversionStripClusterizationAlg",
+                                                useCache=True,
                                                 ClustersKey="ITkConversionStripClusters",
-                                                useCache=False,
+                                                ClusterCache="ActsConversionStripClustersCache",
                                                 RoIs="ActsConversionRegionOfInterest"))
         
     if flags.Detector.EnableITkStrip:
@@ -241,8 +242,8 @@ def ActsConversionClusterizationCfg(flags) -> ComponentAccumulator:
                                                     RoIs="ActsConversionRegionOfInterest",
                                                     useCache=flags.Acts.useCache,
                                                     InputCollection="ITkStripClusters",
-                                                    OutputCollection="ITkConversionStripClusters" if not flags.Acts.useCache else "ITkConversionStripClusters_InView",
-                                                    InputIDC="ActsStripClustersCache"))
+                                                    OutputCollection="ITkConversionStripClusters" if not flags.Acts.useCache else "ITkConversionStripClusters_Cached",
+                                                    InputIDC="ActsStripClustersCache" if not flags.Acts.useCache else "ActsConversionStripClustersCache"))
 
     # Analysis extensions
     if flags.Acts.doAnalysis:
diff --git a/Tracking/Acts/ActsConfig/python/ActsSeedingConfig.py b/Tracking/Acts/ActsConfig/python/ActsSeedingConfig.py
index 63c7884d09692c6dc54a73becbedf722bd2680de..773e87c2f3a44fa58f8976a3d838834c7e93e796 100644
--- a/Tracking/Acts/ActsConfig/python/ActsSeedingConfig.py
+++ b/Tracking/Acts/ActsConfig/python/ActsSeedingConfig.py
@@ -246,7 +246,7 @@ def ActsPixelSeedingAlgCfg(flags,
                 kwargs.setdefault('SeedTool', acc.popToolsAndMerge(ActsPixelSeedingToolCfg(flags)))
 
     kwargs.setdefault("useFastTracking", flags.Tracking.doITkFastTracking)
-    kwargs.setdefault('InputSpacePoints', ['ITkPixelSpacePoints'])
+    kwargs.setdefault('InputSpacePoints', ['ITkPixelSpacePoints_Cached'] if flags.Acts.useCache else ['ITkPixelSpacePoints'])
     kwargs.setdefault('OutputSeeds', 'ActsPixelSeeds')
     kwargs.setdefault('OutputEstimatedTrackParameters', 'ActsPixelEstimatedTrackParams')
     kwargs.setdefault('DetectorElements', 'ITkPixelDetectorElementCollection')
@@ -288,7 +288,7 @@ def ActsStripSeedingAlgCfg(flags,
         else:
             kwargs.setdefault('SeedTool', acc.popToolsAndMerge(ActsStripSeedingToolCfg(flags)))
 
-    kwargs.setdefault('InputSpacePoints', ['ITkStripSpacePoints', 'ITkStripOverlapSpacePoints'])
+    kwargs.setdefault('InputSpacePoints', ['ITkStripSpacePoints_Cached', 'ITkStripOverlapSpacePoints_Cached'] if flags.Acts.useCache else ['ITkStripSpacePoints', 'ITkStripOverlapSpacePoints'])
     kwargs.setdefault('OutputSeeds', 'ActsStripSeeds')
     kwargs.setdefault('OutputEstimatedTrackParameters', 'ActsStripEstimatedTrackParams')
     kwargs.setdefault('DetectorElements', 'ITkStripDetectorElementCollection')
@@ -329,7 +329,7 @@ def ActsConversionSeedingCfg(flags) -> ComponentAccumulator:
     if flags.Detector.EnableITkStrip:
         acc.merge(ActsStripSeedingAlgCfg(flags,
                                          name="ActsConversionStripSeedingAlg",
-                                         InputSpacePoints=["ITkConversionStripSpacePoints"],
+                                         InputSpacePoints=["ITkConversionStripSpacePoints_Cached" if flags.Acts.useCache else "ITkConversionStripSpacePoints"],
                                          OutputSeeds="ActsConversionStripSeeds",
                                          OutputEstimatedTrackParameters="ActsConversionStripEstimatedTrackParams"))
 
diff --git a/Tracking/Acts/ActsConfig/python/ActsSpacePointFormationConfig.py b/Tracking/Acts/ActsConfig/python/ActsSpacePointFormationConfig.py
index becf67ca477f1c53165db758192cc960f0b93a53..7faa0b608710bfb31fcc9d1fc87ca5139ff54b7b 100644
--- a/Tracking/Acts/ActsConfig/python/ActsSpacePointFormationConfig.py
+++ b/Tracking/Acts/ActsConfig/python/ActsSpacePointFormationConfig.py
@@ -3,6 +3,17 @@
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
 
+def ActsSpacePointCacheCreatorCfg(flags, name: str = "ActsSPCacheCreator", **kwargs):
+    kwargs.setdefault("PixelSPCacheKey", "ActsPixelSPCache_Back")
+    kwargs.setdefault("StripSPCacheKey", "ActsStripSPCache_Back")
+    kwargs.setdefault("StripOSPCacheKey", "ActsStripOSPCache_Back")
+
+    acc = ComponentAccumulator()
+
+    acc.addEventAlgo(CompFactory.ActsTrk.Cache.CreatorAlg(name, **kwargs))
+
+    return acc
+
 def ActsPixelSpacePointToolCfg(flags,
                                name: str = "ActsPixelSpacePointTool",
                                **kwargs) -> ComponentAccumulator:
@@ -98,7 +109,14 @@ def ActsPixelSpacePointFormationAlgCfg(flags,
         from ActsConfig.ActsMonitoringConfig import ActsPixelSpacePointFormationMonitoringToolCfg
         kwargs.setdefault("MonTool", acc.popToolsAndMerge(ActsPixelSpacePointFormationMonitoringToolCfg(flags)))
 
-    acc.addEventAlgo(CompFactory.ActsTrk.PixelSpacePointFormationAlg(name, **kwargs))
+
+    if flags.Acts.useCache:
+        kwargs.setdefault('SPCacheBackend', 'ActsPixelSPCache_Back')
+        kwargs.setdefault('SPCache', 'ActsPixelSPCache')
+        acc.addEventAlgo(CompFactory.ActsTrk.PixelCacheSpacePointFormationAlg(name, **kwargs))
+    else:
+        acc.addEventAlgo(CompFactory.ActsTrk.PixelSpacePointFormationAlg(name, **kwargs))
+    
     return acc
 
 def ActsStripSpacePointFormationAlgCfg(flags,
@@ -124,15 +142,69 @@ def ActsStripSpacePointFormationAlgCfg(flags,
         from ActsConfig.ActsMonitoringConfig import ActsStripSpacePointFormationMonitoringToolCfg
         kwargs.setdefault("MonTool", acc.popToolsAndMerge(ActsStripSpacePointFormationMonitoringToolCfg(flags)))
 
-    acc.addEventAlgo(CompFactory.ActsTrk.StripSpacePointFormationAlg(name, **kwargs))
+
+
+    if flags.Acts.useCache:
+        kwargs.setdefault('SPCacheBackend', 'ActsStripSPCache_Back')
+        kwargs.setdefault('SPCache', 'ActsStripSPCache')
+        kwargs.setdefault('OSPCacheBackend', 'ActsStripOSPCache_Back')
+        kwargs.setdefault('OSPCache', 'ActsStripOSPCache')
+        acc.addEventAlgo(CompFactory.ActsTrk.StripCacheSpacePointFormationAlg(name, **kwargs))
+    else:
+        acc.addEventAlgo(CompFactory.ActsTrk.StripSpacePointFormationAlg(name, **kwargs))
+    return acc
+
+def ActsPixelSpacePointCacheDataPreparationAlgCfg(flags,name: str="ActsPixelSpacePointCacheDataPreparationAlg", **kwargs):
+    kwargs.setdefault("InputIDC", "ActsPixelSPCache")
+    kwargs.setdefault("OutputCollection", "ITkPixelSpacePoints_Cached")
+
+    acc = ComponentAccumulator()
+
+    if 'RegSelTool' not in kwargs:
+        from RegionSelector.RegSelToolConfig import regSelTool_ITkStrip_Cfg
+        kwargs.setdefault('RegSelTool', acc.popToolsAndMerge(regSelTool_ITkStrip_Cfg(flags)))
+        
+    acc.addEventAlgo(CompFactory.ActsTrk.SpacePointCacheDataPreparationAlg(name, **kwargs))
+
+    return acc
+
+def ActsStripSpacePointCacheDataPreparationAlgCfg(flags,name: str="ActsStripSpacePointCacheDataPreparationAlg", **kwargs):
+    kwargs.setdefault("InputIDC", "ActsStripSPCache")
+    kwargs.setdefault("OutputCollection", "ITkStripSpacePoints_Cached")
+
+    acc = ComponentAccumulator()
+
+    if 'RegSelTool' not in kwargs:
+        from RegionSelector.RegSelToolConfig import regSelTool_ITkStrip_Cfg
+        kwargs.setdefault('RegSelTool', acc.popToolsAndMerge(regSelTool_ITkStrip_Cfg(flags)))
+        
+    acc.addEventAlgo(CompFactory.ActsTrk.SpacePointCacheDataPreparationAlg(name, **kwargs))
+
     return acc
 
-def ActsMainSpacePointFormationCfg(flags) -> ComponentAccumulator:
+def ActsStripOverlapSpacePointCacheDataPreparationAlgCfg(flags,name: str="ActsStripOverlapSpacePointCacheDataPreparationAlg", **kwargs):
+    kwargs.setdefault("InputIDC", "ActsStripOSPCache")
+    kwargs.setdefault("OutputCollection", "ITkStripOverlapSpacePoints_Cached")
+
     acc = ComponentAccumulator()
 
+    if 'RegSelTool' not in kwargs:
+        from RegionSelector.RegSelToolConfig import regSelTool_ITkStrip_Cfg
+        kwargs.setdefault('RegSelTool', acc.popToolsAndMerge(regSelTool_ITkStrip_Cfg(flags)))
+        
+    acc.addEventAlgo(CompFactory.ActsTrk.SpacePointCacheDataPreparationAlg(name, **kwargs))
+
+    return acc
+
+def ActsMainSpacePointFormationCfg(flags, RoIs: str = "ActsRegionOfInterest") -> ComponentAccumulator:
+    acc = ComponentAccumulator()
+
+    if flags.Acts.useCache:
+        acc.merge(ActsSpacePointCacheCreatorCfg(flags))
+
     if flags.Detector.EnableITkPixel:
         acc.merge(ActsPixelSpacePointFormationAlgCfg(flags,
-                                                     PixelClusters = "ITkPixelClusters_InView" if flags.Acts.useCache else "ITkPixelClusters"))
+                                                     PixelClusters = "ITkPixelClusters_Cached" if flags.Acts.useCache else "ITkPixelClusters"))
     if flags.Detector.EnableITkStrip and not flags.Tracking.doITkFastTracking:
         # Need to schedule this here in case the Athena space point formation is not schedule
         # This is because as of now requires at least ITkSiElementPropertiesTableCondAlgCfg
@@ -148,8 +220,16 @@ def ActsMainSpacePointFormationCfg(flags) -> ComponentAccumulator:
         acc.merge(ITkSiElementPropertiesTableCondAlgCfg(flags))
         
         acc.merge(ActsStripSpacePointFormationAlgCfg(flags,
-                                                     StripClusters = "ITkStripClusters_InView" if flags.Acts.useCache else "ITkStripClusters"))
+                                                     StripClusters = "ITkStripClusters_Cached" if flags.Acts.useCache else "ITkStripClusters"))
+
+    if flags.Acts.useCache:
+        if flags.Detector.EnableITkPixel:
+            acc.merge(ActsPixelSpacePointCacheDataPreparationAlgCfg(flags, RoIs=RoIs))
+        if flags.Detector.EnableITkStrip:
+            acc.merge(ActsStripSpacePointCacheDataPreparationAlgCfg(flags, RoIs=RoIs))
+            acc.merge(ActsStripOverlapSpacePointCacheDataPreparationAlgCfg(flags, RoIs=RoIs))
 
+            
     # Analysis extensions
     if flags.Acts.doAnalysis:
         if flags.Detector.EnableITkPixel:
@@ -177,7 +257,6 @@ def ActsConversionSpacePointFormationCfg(flags) -> ComponentAccumulator:
                                                            RoIs = "ActsConversionRegionOfInterest",
                                                            InputCollection = "ITkStripSpacePoints",
                                                            OutputCollection = "ITkConversionStripSpacePoints"))
-            
         else:            
             # Need to schedule this here in case the Athena space point formation is not schedule
             # This is because as of now requires at least ITkSiElementPropertiesTableCondAlgCfg
@@ -194,10 +273,17 @@ def ActsConversionSpacePointFormationCfg(flags) -> ComponentAccumulator:
             
             acc.merge(ActsStripSpacePointFormationAlgCfg(flags,
                                                          name="ActsConversionStripSpacePointFormation",
-                                                         StripClusters="ITkConversionStripClusters_InView",
+                                                         StripClusters="ITkConversionStripClusters_Cached",
                                                          StripSpacePoints="ITkConversionStripSpacePoints",
+                                                         SPCache = "ActsStripConvSPCache",
+                                                         OSPCache = "ActsStripConvOSPCache",
                                                          ProcessOverlapForStrip=False))
             
+            acc.merge(ActsStripSpacePointCacheDataPreparationAlgCfg(flags, "StripSPConvCacheDataPrepAlg",
+                                                                    InputIDC="ActsStripConvSPCache",
+                                                                    OutputCollection="ITkConversionStripSpacePoints_Cached",
+                                                                    RoIs = "ActsConversionRegionOfInterest"))
+            
     # Analysis extensions
     if flags.Acts.doAnalysis:
         if flags.Detector.EnableITkStrip:
@@ -220,6 +306,6 @@ def ActsSpacePointFormationCfg(flags) -> ComponentAccumulator:
         acc.merge(ActsConversionSpacePointFormationCfg(flags))
     # Any other pass -> Validation mainly
     else:
-        acc.merge(ActsMainSpacePointFormationCfg(flags))
+        acc.merge(ActsMainSpacePointFormationCfg(flags, RoIs = f"{flags.Tracking.ActiveConfig.extension}RegionOfInterest"))
 
     return acc
diff --git a/Tracking/Acts/ActsConfig/python/ActsTrackFindingConfig.py b/Tracking/Acts/ActsConfig/python/ActsTrackFindingConfig.py
index c3248a6d4d7d599c7641c3c5dc78239452e68889..a36b934d70e702ca02fa6cfc63395f47db92cf60 100644
--- a/Tracking/Acts/ActsConfig/python/ActsTrackFindingConfig.py
+++ b/Tracking/Acts/ActsConfig/python/ActsTrackFindingConfig.py
@@ -160,12 +160,12 @@ def ActsTrackFindingCfg(flags,
         kwargs.setdefault('SeedLabels', isdet(flags, strip=["SSS"]))
         kwargs.setdefault('EstimatedTrackParametersKeys', isdet(flags, strip=["ActsConversionStripEstimatedTrackParams"]))
         kwargs.setdefault('SeedContainerKeys', isdet(flags, strip=["ActsConversionStripSeeds"]))
-        kwargs.setdefault('UncalibratedMeasurementContainerKeys', isdet(flags, pixel=["ITkPixelClusters_InView"], strip=["ITkConversionStripClusters_InView"]) if flags.Acts.useCache else isdet(flags, pixel=["ITkPixelClusters"], strip=["ITkConversionStripClusters"]))
+        kwargs.setdefault('UncalibratedMeasurementContainerKeys', isdet(flags, pixel=["ITkPixelClusters_Cached"], strip=["ITkConversionStripClusters_Cached"]) if flags.Acts.useCache else isdet(flags, pixel=["ITkPixelClusters"], strip=["ITkConversionStripClusters"]))
     else:
         kwargs.setdefault('SeedLabels', isdet(flags, pixel=["PPP"], strip=["SSS"]) if not flags.Tracking.doITkFastTracking else isdet(flags, pixel=["PPP"]))
         kwargs.setdefault('EstimatedTrackParametersKeys', isdet(flags, pixel=["ActsPixelEstimatedTrackParams"], strip=["ActsStripEstimatedTrackParams"]) if not flags.Tracking.doITkFastTracking else isdet(flags, pixel=["ActsPixelEstimatedTrackParams"]))
         kwargs.setdefault('SeedContainerKeys', isdet(flags, pixel=["ActsPixelSeeds"], strip=["ActsStripSeeds"]) if not flags.Tracking.doITkFastTracking else isdet(flags, pixel=["ActsPixelSeeds"]))
-        kwargs.setdefault('UncalibratedMeasurementContainerKeys', isdet(flags, pixel=["ITkPixelClusters_InView"], strip=["ITkStripClusters_InView"]) if flags.Acts.useCache else isdet(flags, pixel=["ITkPixelClusters"], strip=["ITkStripClusters"]))
+        kwargs.setdefault('UncalibratedMeasurementContainerKeys', isdet(flags, pixel=["ITkPixelClusters_Cached"], strip=["ITkStripClusters_Cached"]) if flags.Acts.useCache else isdet(flags, pixel=["ITkPixelClusters"], strip=["ITkStripClusters"]))
         
     acc.merge(ActsMainTrackFindingAlgCfg(flags,
                                          name=f"{flags.Tracking.ActiveConfig.extension}TrackFindingAlg",
diff --git a/Tracking/Acts/ActsDataPreparation/src/Cache.h b/Tracking/Acts/ActsDataPreparation/src/Cache.h
index 94117c40ed9c95038294244d9fb236da0eb9f070..7589c142457dbece34de10706be151c38f48a888 100644
--- a/Tracking/Acts/ActsDataPreparation/src/Cache.h
+++ b/Tracking/Acts/ActsDataPreparation/src/Cache.h
@@ -28,10 +28,10 @@ namespace ActsTrk::Cache {
     class CacheEntry : public DataObject {
         public:
         CacheEntry(){}
-        CacheEntry(DataVector<OT>* dv, unsigned int s, unsigned int e): container(dv), range_start(s), range_end(e){}
+        CacheEntry(DataVector<OT>* dv, unsigned int s, unsigned int e): container(dv){ranges.emplace_back(std::move(s),std::move(e));}
+        CacheEntry(DataVector<OT>* dv, std::vector<std::pair<unsigned int, unsigned int>>& r): container(dv), ranges(std::move(r)) {}
         DataVector<OT>* container;
-        unsigned int range_start;
-        unsigned int range_end;
+        std::vector<std::pair<unsigned int, unsigned int>> ranges;
     };
 
     template<typename OT>
diff --git a/Tracking/Acts/ActsDataPreparation/src/CacheCreator.cxx b/Tracking/Acts/ActsDataPreparation/src/CacheCreator.cxx
index 0759d4223988a5152b893a0e8e1efe4dcc0bee00..000c24e68c872f9fe8b10da556e9707abce6407b 100644
--- a/Tracking/Acts/ActsDataPreparation/src/CacheCreator.cxx
+++ b/Tracking/Acts/ActsDataPreparation/src/CacheCreator.cxx
@@ -13,9 +13,16 @@ namespace ActsTrk::Cache {
         ATH_CHECK(m_pixelClusterCacheKey.initialize(SG::AllowEmpty));
         ATH_CHECK(m_stripClusterCacheKey.initialize(SG::AllowEmpty));
 
+        ATH_CHECK(m_pixelSPCacheKey.initialize(SG::AllowEmpty));
+        ATH_CHECK(m_stripSPCacheKey.initialize(SG::AllowEmpty));
+        ATH_CHECK(m_stripOSPCacheKey.initialize(SG::AllowEmpty));
+
         m_do_pixClusters = !m_pixelClusterCacheKey.key().empty();
         m_do_stripClusters = !m_stripClusterCacheKey.key().empty();
 
+        m_do_pixSP = !m_pixelSPCacheKey.key().empty();
+        m_do_stripSP = !m_stripSPCacheKey.key().empty();
+
         ATH_CHECK(detStore()->retrieve(m_pix_idHelper, "PixelID"));
         ATH_CHECK(detStore()->retrieve(m_strip_idHelper, "SCT_ID"));
         
@@ -31,6 +38,16 @@ namespace ActsTrk::Cache {
             ATH_CHECK(createContainer(m_stripClusterCacheKey, m_strip_idHelper->wafer_hash_max(), ctx));
         }
 
+        if(m_do_pixSP){
+            ATH_CHECK(createContainer(m_pixelSPCacheKey, m_pix_idHelper->wafer_hash_max(), ctx));
+        }
+
+        if(m_do_stripSP){
+            ATH_CHECK(createContainer(m_stripSPCacheKey, m_strip_idHelper->wafer_hash_max(), ctx));
+            ATH_CHECK(createContainer(m_stripOSPCacheKey, m_strip_idHelper->wafer_hash_max(), ctx));
+	    ATH_MSG_DEBUG("created strip sp containers");
+        }
+
         return StatusCode::SUCCESS;
     }
-}
\ No newline at end of file
+}
diff --git a/Tracking/Acts/ActsDataPreparation/src/CacheCreator.h b/Tracking/Acts/ActsDataPreparation/src/CacheCreator.h
index 23df9b0d56ad5152deae483ffe0c122a494a5c0c..67cef5ad29c420ee0f0663421550db756930003e 100644
--- a/Tracking/Acts/ActsDataPreparation/src/CacheCreator.h
+++ b/Tracking/Acts/ActsDataPreparation/src/CacheCreator.h
@@ -10,8 +10,9 @@
 
 #include <InDetIdentifier/PixelID.h>
 #include <InDetIdentifier/SCT_ID.h>
-#include "xAODInDetMeasurement/PixelCluster.h"
-#include "xAODInDetMeasurement/StripCluster.h"
+#include "details/PixelClusterCacheId.h"
+#include "details/StripClusterCacheId.h"
+#include "details/SPCacheId.h"
 
 namespace ActsTrk::Cache{
     class CreatorAlg: public IDCCacheCreatorBase{
@@ -24,6 +25,10 @@ namespace ActsTrk::Cache{
         SG::WriteHandleKey<Handles<xAOD::PixelCluster>::IDCBackend> m_pixelClusterCacheKey{this, "PixelClustersCacheKey", ""};
         SG::WriteHandleKey<Handles<xAOD::StripCluster>::IDCBackend> m_stripClusterCacheKey{this, "StripClustersCacheKey", ""};
 
+        SG::WriteHandleKey<Handles<xAOD::SpacePoint>::IDCBackend> m_pixelSPCacheKey{this, "PixelSPCacheKey", ""};
+        SG::WriteHandleKey<Handles<xAOD::SpacePoint>::IDCBackend> m_stripSPCacheKey{this, "StripSPCacheKey", ""};
+        SG::WriteHandleKey<Handles<xAOD::SpacePoint>::IDCBackend> m_stripOSPCacheKey{this, "StripOSPCacheKey", ""};
+
         const PixelID* m_pix_idHelper{};
         const SCT_ID*  m_strip_idHelper{};
 
@@ -34,7 +39,4 @@ namespace ActsTrk::Cache{
         bool m_do_stripClusters{false};
     };
 }
-
-CLASS_DEF(ActsTrk::Cache::Handles<xAOD::PixelCluster>::IDCBackend, 70424203, 1);
-CLASS_DEF(ActsTrk::Cache::Handles<xAOD::StripCluster>::IDCBackend, 202232989, 1);
 #endif
diff --git a/Tracking/Acts/ActsDataPreparation/src/CollectionDataPreparationAlg.h b/Tracking/Acts/ActsDataPreparation/src/CollectionDataPreparationAlg.h
index 7aab774aabc893b72ad4573c021a072fc8cd7b58..7eeee5b27b8d0b9201f86829922231f91d840a69 100644
--- a/Tracking/Acts/ActsDataPreparation/src/CollectionDataPreparationAlg.h
+++ b/Tracking/Acts/ActsDataPreparation/src/CollectionDataPreparationAlg.h
@@ -60,6 +60,12 @@ namespace ActsTrk {
     virtual xAOD::DetectorIDHashType retrieveDetectorIDHash(const xAOD::SpacePoint& obj) const;
   };
 
+  class SpacePointCacheDataPreparationAlg
+    : public DataPreparationAlg< xAOD::SpacePointContainer, true > {
+  public:
+    using DataPreparationAlg<xAOD::SpacePointContainer, true>::DataPreparationAlg;
+  };
+
 } // namespace
 
 #include "CollectionDataPreparationAlg.icc"
diff --git a/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.cxx b/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.cxx
index 99bbc21b6d4a1f50c243edc79f6ed3665fae627b..b59a763b644f925879d0a200ff7b954c3adaf84b 100644
--- a/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.cxx
+++ b/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.cxx
@@ -54,7 +54,9 @@ namespace ActsTrk
 								  const Amg::Vector3D &beamSpotVertex,
 								  std::vector<StripSP>& spacePoints,
 								  std::vector<StripSP>& overlapSpacePoints,
-								  bool processOverlaps) const
+								  bool processOverlaps,
+									const std::vector<IdentifierHash>& hashesToProcess,
+									ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>& stripAccessor) const
   {
     /// Production of ActsTrk::SpacePoint from strip clusters
     /// Strip space points involves a more complex logic since
@@ -166,15 +168,8 @@ namespace ActsTrk
 
     auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
 
-    ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>
-      stripAccessor(
-		    clusterContainer,
-		    [](const xAOD::StripCluster &cl)
-		    { return cl.identifierHash(); },
-		    elements.size());
-
-    const auto &allIdHashes = stripAccessor.allIdentifiers();
-    for (auto &idHash : allIdHashes)
+    const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.allIdentifiers());
+    for (auto &idHash : hashesProc)
       {
 	const InDetDD::SiDetectorElement *thisElement = elements.getDetectorElement(idHash);
 	if (thisElement->isStereo())
diff --git a/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.h b/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.h
index 93a59d28bdc7f75a6dbebb8e1b1ebecf5c72e6ce..0b4844dc3e91b0de22a910517b730713734392eb 100644
--- a/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.h
+++ b/Tracking/Acts/ActsDataPreparation/src/CoreStripSpacePointFormationTool.h
@@ -52,7 +52,9 @@ namespace ActsTrk {
 					   const Amg::Vector3D& beamSpotVertex,
 					   std::vector<StripSP>& spacePoints,
 					   std::vector<StripSP>& overlapSpacePoints,
-					   bool processOverlaps ) const override;
+					   bool processOverlaps,
+					   const std::vector<IdentifierHash>& hashesToProcess,
+					   ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>& stripAccessor ) const override;
 
   private:
 
diff --git a/Tracking/Acts/ActsDataPreparation/src/PixelClusterizationAlg.h b/Tracking/Acts/ActsDataPreparation/src/PixelClusterizationAlg.h
index a8fde6be3ac71fb814c3bac88da03d2894211dad..ac4d83cfa1173291cbde43495d3b4ef7a7940db2 100644
--- a/Tracking/Acts/ActsDataPreparation/src/PixelClusterizationAlg.h
+++ b/Tracking/Acts/ActsDataPreparation/src/PixelClusterizationAlg.h
@@ -3,6 +3,7 @@
 */
 
 #include <ActsToolInterfaces/IPixelClusteringTool.h>
+#include "details/PixelClusterCacheId.h"
 #include "details/ClusterizationAlg.h"
 
 namespace ActsTrk {
diff --git a/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.h b/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.h
index e28d6b1a3d401b0227f536edfda11e5b55dbf882..9d5da20e81ab1fea3ca3a919b01e149e87858151 100644
--- a/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.h
+++ b/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.h
@@ -2,82 +2,14 @@
   Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef ACTSTRK_DATAPREPARATION_PIXELSPACEPOINTFORMATIONALG_H
-#define ACTSTRK_DATAPREPARATION_PIXELSPACEPOINTFORMATIONALG_H
-
-#include "AthenaBaseComps/AthReentrantAlgorithm.h"
-#include "GaudiKernel/ToolHandle.h"
-#include "AthenaMonitoringKernel/GenericMonitoringTool.h"
-
-#include "StoreGate/ReadHandleKey.h"
-#include "StoreGate/WriteHandleKey.h"
-#include "StoreGate/ReadCondHandleKey.h"
-
-#include "ActsToolInterfaces/IPixelSpacePointFormationTool.h"
-
-#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
-
-#include "xAODInDetMeasurement/PixelClusterContainer.h"
-#include "xAODInDetMeasurement/SpacePointContainer.h"
-#include "xAODInDetMeasurement/SpacePointAuxContainer.h"
-
-#include <string>
+#include "details/PixelSpacePointFormationAlgBase.h"
 
 namespace ActsTrk {
-
-    /// @class PixelSpacePointFormationAlg
-    /// This version of PixelSpacePointFormationAlg uses xAOD pixel clusters
-    /// to find space points in the ITk pixeldetectors.
-    /// Pixel space points are obtained directly from the clusters,
-    /// with needed evaluation of the space point covariance terms
-    /// Space points are then recorded to storegate as ActsTrk::SpacePoint
-    /// into an ActsTrk::SpacePointContainer.
-
-    class PixelSpacePointFormationAlg : public AthReentrantAlgorithm {
-    public:
-        /// @name AthReentrantAlgorithm methods
-        //@{
-        PixelSpacePointFormationAlg(const std::string& name,
-				    ISvcLocator* pSvcLocator);
-        virtual ~PixelSpacePointFormationAlg() = default;
-        virtual StatusCode initialize() override;
-        virtual StatusCode execute (const EventContext& ctx) const override;
-        //@}
-
-    private:
-        /// @name Disallow constructor without parameters, copy constructor, assignment operator
-        //@{
-        PixelSpacePointFormationAlg() = delete;
-        PixelSpacePointFormationAlg(const PixelSpacePointFormationAlg&) = delete;
-        PixelSpacePointFormationAlg &operator=(const PixelSpacePointFormationAlg&) = delete;
-        //@}
-
-        /// @name Input data using SG::ReadHandleKey
-        //@{
-        SG::ReadHandleKey<xAOD::PixelClusterContainer> m_pixelClusterContainerKey{this, "PixelClusters", "", "name of the input pixel cluster container"};
-        //@}
-
-        /// @name Input condition data using SG::ReadCondHandleKey
-        //@{
-        /// To get detector elements
-        SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_pixelDetEleCollKey{this, "PixelDetectorElements", "ITkPixelDetectorElementCollection", "Key of input SiDetectorElementCollection for Pixel"};
-        //@}
-
-        ///@name Output data using SG::WriteHandleKey
-        //@{
-	SG::WriteHandleKey<xAOD::SpacePointContainer> m_pixelSpacePointContainerKey {this, "PixelSpacePoints", "", "name of the output pixel space point container"};
-        //@}
-
-        /// @name ToolHandle
-        //@{
-        /// For space point formation
-        ToolHandle<ActsTrk::IPixelSpacePointFormationTool> m_spacePointMakerTool{this, "SpacePointFormationTool", "", "Tool dedicated to the creation of pixel space points"};
-        /// For monitoring
-        ToolHandle<GenericMonitoringTool> m_monTool{this, "MonTool", "", "Monitoring tool"};
-        //@}
-
-  };
-
-}
-
-#endif // ACTSTRKSPACEPOINTFORMATION_PIXELSPACEPOINTFORMATIONALG_H
+    class PixelSpacePointFormationAlg: public PixelSpacePointFormationAlgBase<false>{
+        using PixelSpacePointFormationAlgBase<false>::PixelSpacePointFormationAlgBase;
+    };
+
+    class PixelCacheSpacePointFormationAlg: public PixelSpacePointFormationAlgBase<true>{
+        using PixelSpacePointFormationAlgBase<true>::PixelSpacePointFormationAlgBase;
+    };
+};
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/StripClusterizationAlg.h b/Tracking/Acts/ActsDataPreparation/src/StripClusterizationAlg.h
index 3065c91d9a16a87098af4d7a854d001c6f50152b..058bb2fe7b342d93c8b67f5a1df38d4374f48334 100644
--- a/Tracking/Acts/ActsDataPreparation/src/StripClusterizationAlg.h
+++ b/Tracking/Acts/ActsDataPreparation/src/StripClusterizationAlg.h
@@ -3,6 +3,7 @@
 */
 
 #include <ActsToolInterfaces/IStripClusteringTool.h>
+#include "details/StripClusterCacheId.h"
 #include "details/ClusterizationAlg.h"
 
 namespace ActsTrk {
diff --git a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.cxx b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.cxx
deleted file mode 100644
index 11340f629ab4b7590ebf33e6078a209dd0927eb2..0000000000000000000000000000000000000000
--- a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.cxx
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "StripSpacePointFormationAlg.h"
-
-#include "InDetReadoutGeometry/SiDetectorElement.h"
-
-#include "xAODInDetMeasurement/StripClusterAuxContainer.h"
-
-#include "AthenaMonitoringKernel/Monitored.h"
-
-namespace ActsTrk {
-
-  //------------------------------------------------------------------------
-  StripSpacePointFormationAlg::StripSpacePointFormationAlg(const std::string& name,
-							   ISvcLocator* pSvcLocator)
-    : AthReentrantAlgorithm(name, pSvcLocator)
-    {}
-
-  //-----------------------------------------------------------------------
-  StatusCode StripSpacePointFormationAlg::initialize()
-  {
-    ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
-
-    ATH_CHECK( m_stripClusterContainerKey.initialize() );
-    ATH_CHECK( m_stripSpacePointContainerKey.initialize() );
-    ATH_CHECK( m_stripOverlapSpacePointContainerKey.initialize( m_processOverlapForStrip) );
-    ATH_CHECK( m_stripDetEleCollKey.initialize() );
-    ATH_CHECK( m_stripPropertiesKey.initialize() );
-
-    ATH_CHECK( m_beamSpotKey.initialize() );
-
-    if ( not m_monTool.empty() )
-      ATH_CHECK( m_monTool.retrieve() );
-
-    return StatusCode::SUCCESS;
-  }
-
-  //-------------------------------------------------------------------------
-  StatusCode StripSpacePointFormationAlg::execute (const EventContext& ctx) const
-  {
-    auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
-    auto nReceivedSPsStrip = Monitored::Scalar<int>( "numStripSpacePoints" , 0 );
-    auto nReceivedSPsStripOverlap = Monitored::Scalar<int>( "numStripOverlapSpacePoints" , 0 );
-    auto mon = Monitored::Group( m_monTool, timer, nReceivedSPsStrip, nReceivedSPsStripOverlap );
-
-    SG::ReadHandle<xAOD::StripClusterContainer> inputStripClusterContainer( m_stripClusterContainerKey, ctx );
-    if (!inputStripClusterContainer.isValid()){
-        ATH_MSG_FATAL("xAOD::StripClusterContainer with key " << m_stripClusterContainerKey.key() << " is not available...");
-        return StatusCode::FAILURE;
-    }
-    const xAOD::StripClusterContainer* inputClusters = inputStripClusterContainer.cptr();
-    ATH_MSG_DEBUG("Retrieved " << inputClusters->size() << " clusters from container " << m_stripClusterContainerKey.key());
-
-    
-    auto stripSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripSpacePointContainerKey, ctx );
-    ATH_MSG_DEBUG( "--- Strip Space Point Container `" << m_stripSpacePointContainerKey.key() << "` created ..." );
-    ATH_CHECK( stripSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
-						std::make_unique<xAOD::SpacePointAuxContainer>() ));
-    xAOD::SpacePointContainer* spacePoints = stripSpacePointContainer.ptr();
-
-    
-    xAOD::SpacePointContainer* overlapSpacePoints = nullptr;
-    SG::WriteHandle<xAOD::SpacePointContainer> stripOverlapSpacePointContainer;
-    if (m_processOverlapForStrip) {
-      stripOverlapSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripOverlapSpacePointContainerKey, ctx );
-      ATH_MSG_DEBUG( "--- Strip Overlap Space Point Container `" << m_stripOverlapSpacePointContainerKey.key() << "` created ..." );
-      ATH_CHECK( stripOverlapSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
-							 std::make_unique<xAOD::SpacePointAuxContainer>() ));
-      overlapSpacePoints = stripOverlapSpacePointContainer.ptr();     
-    }
-
-
-    // Early exit in case we have no clusters
-    // We still are saving an empty space point container in SG
-    if (inputClusters->empty()) {
-      ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
-      return StatusCode::SUCCESS;
-    }
-
-    
-    SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
-    const InDet::BeamSpotData* beamSpot = *beamSpotHandle;
-    auto vertex = beamSpot->beamVtx().position();
-
-
-
-    SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> stripDetEleHandle(m_stripDetEleCollKey, ctx);
-    const InDetDD::SiDetectorElementCollection* stripElements(*stripDetEleHandle);
-    if (not stripDetEleHandle.isValid() or stripElements==nullptr) {
-      ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " is not available.");
-      return StatusCode::FAILURE;
-    }
-
-    SG::ReadCondHandle<InDet::SiElementPropertiesTable> stripProperties(m_stripPropertiesKey, ctx);
-    const InDet::SiElementPropertiesTable* properties = stripProperties.retrieve();
-    if (properties==nullptr) {
-      ATH_MSG_FATAL("Pointer of SiElementPropertiesTable (" << m_stripPropertiesKey.fullKey() << ") could not be retrieved");
-      return StatusCode::FAILURE;
-    }
-
-
-    // Produce space points
-    std::vector<StripSP> sps;
-    std::vector<StripSP> osps;
-    sps.reserve(inputStripClusterContainer->size() * 0.5);
-    osps.reserve(inputStripClusterContainer->size() * 0.5);
-
-    ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
-							 *inputClusters,
-							 *properties,
-							 *stripElements,
-							 vertex,
-							 sps,
-							 osps,
-							 m_processOverlapForStrip) );
-
-    // using trick for fast insertion
-    spacePoints->reserve(sps.size());
-
-    std::vector<xAOD::SpacePoint*> sp_collection;
-    sp_collection.reserve(sps.size());
-    for (std::size_t i(0); i<sps.size(); ++i)
-      sp_collection.push_back(new xAOD::SpacePoint());
-    spacePoints->insert(spacePoints->end(), sp_collection.begin(), sp_collection.end());
-
-    // fill
-    for (std::size_t i(0); i<sps.size(); ++i) {
-      auto& toAdd = sps.at(i);
-
-      // make link to Clusters
-      std::vector< const xAOD::UncalibratedMeasurement* > els(
-							      {inputClusters->at(toAdd.measurementIndexes[0]),
-							       inputClusters->at(toAdd.measurementIndexes[1])}
-							      );
-      spacePoints->at(i)->setSpacePoint(toAdd.idHashes, 
-					toAdd.globPos,
-					toAdd.cov_r,
-					toAdd.cov_z,
-					els,
-					toAdd.topHalfStripLength,
-					toAdd.bottomHalfStripLength,
-					toAdd.topStripDirection,
-					toAdd.bottomStripDirection,
-					toAdd.stripCenterDistance,
-					toAdd.topStripCenter);
-    }
-
-    nReceivedSPsStrip = stripSpacePointContainer->size();
-    
-    // overlap space points now
-    if (not m_processOverlapForStrip or not overlapSpacePoints) {
-      return StatusCode::SUCCESS;
-    }
-    
-    overlapSpacePoints->reserve(osps.size());
-
-    std::vector<xAOD::SpacePoint*> sp_overlap_collection;
-    sp_overlap_collection.reserve(osps.size());
-    for (std::size_t i(0); i<osps.size(); ++i)
-      sp_overlap_collection.push_back(new xAOD::SpacePoint());
-    overlapSpacePoints->insert(overlapSpacePoints->end(), sp_overlap_collection.begin(), sp_overlap_collection.end());
-      
-    for (std::size_t i(0); i<osps.size(); ++i) {
-      auto& toAdd = osps.at(i);
-      std::vector< const xAOD::UncalibratedMeasurement* > oels(
-							       {inputClusters->at(toAdd.measurementIndexes[0]),
-								inputClusters->at(toAdd.measurementIndexes[1])}
-							       );
-      overlapSpacePoints->at(i)->setSpacePoint(toAdd.idHashes, 
-					       toAdd.globPos,
-					       toAdd.cov_r,
-					       toAdd.cov_z,
-					       oels,
-					       toAdd.topHalfStripLength,
-					       toAdd.bottomHalfStripLength,
-					       toAdd.topStripDirection,
-					       toAdd.bottomStripDirection,
-					       toAdd.stripCenterDistance,
-					       toAdd.topStripCenter);
-    }
-    
-    nReceivedSPsStripOverlap = overlapSpacePoints->size();
-
-    return StatusCode::SUCCESS;
-  }
-
-}
diff --git a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.h b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.h
index 90e778f85ffc290caed40c579957ead5e7e180c4..3a33bc30e228740b8f7d2121705b50cc8c60c440 100644
--- a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.h
+++ b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationAlg.h
@@ -2,99 +2,14 @@
   Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef ACTSTRK_DATAPREPARATION_STRIPSPACEPOINTFORMATIONALG_H
-#define ACTSTRK_DATAPREPARATION_STRIPSPACEPOINTFORMATIONALG_H
-
-#include "AthenaBaseComps/AthReentrantAlgorithm.h"
-#include "GaudiKernel/ToolHandle.h"
-#include "AthenaMonitoringKernel/GenericMonitoringTool.h"
-
-#include "StoreGate/ReadHandleKey.h"
-#include "StoreGate/WriteHandleKey.h"
-#include "StoreGate/ReadCondHandleKey.h"
-
-#include "ActsToolInterfaces/IStripSpacePointFormationTool.h"
-
-#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
-#include "SiSpacePointFormation/SiElementPropertiesTable.h"
-#include "BeamSpotConditionsData/BeamSpotData.h"
-
-#include "xAODInDetMeasurement/StripClusterContainer.h"
-#include "xAODInDetMeasurement/SpacePointContainer.h"
-#include "xAODInDetMeasurement/SpacePointAuxContainer.h"
-
-#include <string>
+#include "details/StripSpacePointFormationAlgBase.h"
 
 namespace ActsTrk {
-    /// @class StripSpacePointFormationAlg
-    /// This version of StripSpacePointFormationAlg uses xAOD strip clusters
-    /// to find space points in the ITk strip detectors.
-    /// Strip space points are made by combining clusters from pairs of
-    /// overlapping detectors. The access to overlapping detector elements is
-    /// possible using the ContainerAccessor.
-    /// The user can choose just to process the detector element and
-    /// its opposite on the stereo layer, or also to consider overlaps with the
-    /// four nearest neighbours of the opposite elements.
-    ///
-    /// Space points are then recorded to storegate as ActsTrk::SpacePoint
-    /// into an ActsTrk::SpacePointContainer.
-
-    class StripSpacePointFormationAlg : public AthReentrantAlgorithm {
-    public:
-        /// @name AthReentrantAlgorithm methods
-        //@{
-        StripSpacePointFormationAlg(const std::string& name,
-				    ISvcLocator* pSvcLocator);
-        virtual ~StripSpacePointFormationAlg() = default;
-        virtual StatusCode initialize() override;
-        virtual StatusCode execute (const EventContext& ctx) const override;
-        //@}
-
-    private:
-        /// @name Disallow constructor without parameters, copy constructor, assignment operator
-        //@{
-        StripSpacePointFormationAlg() = delete;
-        StripSpacePointFormationAlg(const StripSpacePointFormationAlg&) = delete;
-        StripSpacePointFormationAlg &operator=(const StripSpacePointFormationAlg&) = delete;
-        //@}
-
-        /// @name Input data using SG::ReadHandleKey
-        //@{
-        SG::ReadHandleKey<xAOD::StripClusterContainer>  m_stripClusterContainerKey{this, "StripClusters", "", "name of the input strip cluster container"};
-        //@}
-
-        /// @name Input condition data using SG::ReadCondHandleKey
-        //@{
-        /// To get beam spot data
-        SG::ReadCondHandleKey<InDet::BeamSpotData> m_beamSpotKey { this, "BeamSpotKey", "BeamSpotData", "SG key for beam spot" };
-
-        /// To get detector elements
-        SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_stripDetEleCollKey{this, "StripDetectorElements", "ITkStripDetectorElementCollection", "Key of input SiDetectorElementCollection for Strip"};
-        /// To get strip module neighbours
-        SG::ReadCondHandleKey<InDet::SiElementPropertiesTable> m_stripPropertiesKey{this, "StripElementPropertiesTable", "ITkStripElementPropertiesTable", "Key of input SiElementPropertiesTable for Strip"};
-        //@}
-
-        ///@name Output data using SG::WriteHandleKey
-        //@{
-	SG::WriteHandleKey<xAOD::SpacePointContainer> m_stripSpacePointContainerKey{this, "StripSpacePoints", "", "name of the output strip space point container"};
-	SG::WriteHandleKey<xAOD::SpacePointContainer> m_stripOverlapSpacePointContainerKey{this, "StripOverlapSpacePoints", "", "name of the strip overlap strip space point container"};
-        //@}
-
-        /// @name ToolHandle
-        //@{
-        /// For space point formation
-        ToolHandle<ActsTrk::IStripSpacePointFormationTool> m_spacePointMakerTool{this, "SpacePointFormationTool", "", "Tool dedicated to the creation of pixel space points"};
-        /// For monitoring
-        ToolHandle<GenericMonitoringTool> m_monTool{this, "MonTool", "", "Monitoring tool"};
-        //@}
-
-        /// @name Configuration flags
-        //@{
-        Gaudi::Property< bool > m_processOverlapForStrip{this, "ProcessOverlapForStrip", true, "Enable production of eta/phi overlapping strip space points."};
-        //@}
-
-  };
-
-}
-
-#endif // ACTSTRKSPACEPOINTFORMATION_STRIPSPACEPOINTFORMATIONALG_H
+    class StripSpacePointFormationAlg: public StripSpacePointFormationAlgBase<false>{
+        using StripSpacePointFormationAlgBase<false>::StripSpacePointFormationAlgBase;
+    };
+
+    class StripCacheSpacePointFormationAlg: public StripSpacePointFormationAlgBase<true>{
+        using StripSpacePointFormationAlgBase<true>::StripSpacePointFormationAlgBase;
+    };
+};
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.cxx b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.cxx
index f1a7dd8e0f68ac43cecbc88adc97fb507e154204..a53a2652298619d71da5e38d57318eb13a4b2894 100644
--- a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.cxx
+++ b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.cxx
@@ -35,7 +35,9 @@ namespace ActsTrk {
 							      const Amg::Vector3D& beamSpotVertex,
 							      std::vector<StripSP>& spacePoints,
 							      std::vector<StripSP>& overlapSpacePoints,
-							      bool processOverlaps) const
+							      bool processOverlaps,
+							      const std::vector<IdentifierHash>& hashesToProcess,
+							      ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>& stripAccessor) const
     {
         /// Production of StripSP from strip clusters
         /// Strip space points involves a more complex logic since
@@ -79,13 +81,8 @@ namespace ActsTrk {
         /// Access to the cluster from a given detector element is possible
         /// via the ContainerAccessor.
 
-        ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>
-            stripAccessor ( clusterContainer,
-                            [](const xAOD::StripCluster& cl) { return cl.identifierHash();},
-                            elements.size());
-
-        const auto& allIdHashes = stripAccessor.allIdentifiers();
-        for (auto& idHash : allIdHashes) {
+        const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.allIdentifiers());
+        for (auto& idHash : hashesProc) {
             const InDetDD::SiDetectorElement* thisElement = elements.getDetectorElement(idHash);
             if ( not thisElement->isStereo() ) {
                 // Retrieve the neighbours of the detector element
diff --git a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.h b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.h
index cf7fb784a1ee6fb6fa2c9327e869788196e8bc60..94a2ea772a94a4635fc6b768701bcf4269e6f616 100644
--- a/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.h
+++ b/Tracking/Acts/ActsDataPreparation/src/StripSpacePointFormationTool.h
@@ -44,14 +44,16 @@ namespace ActsTrk {
 
         /// @name Production of space points
         //@{
-      virtual StatusCode produceSpacePoints(const EventContext& ctx,
+        virtual StatusCode produceSpacePoints(const EventContext& ctx,
 					    const xAOD::StripClusterContainer& clusterContainer,
 					    const InDet::SiElementPropertiesTable& properties,
 					    const InDetDD::SiDetectorElementCollection& elements,
 					    const Amg::Vector3D& beamSpotVertex,
 					    std::vector<StripSP>& spacePoints,
 					    std::vector<StripSP>& overlapSpacePoints,
-					    bool processOverlaps) const override;
+					    bool processOverlaps,
+					    const std::vector<IdentifierHash>& hashesToProcess,
+					    ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>& stripAccessor ) const override;
         //@}
 
     private:
diff --git a/Tracking/Acts/ActsDataPreparation/src/components/ActsDataPreparation_entries.cxx b/Tracking/Acts/ActsDataPreparation/src/components/ActsDataPreparation_entries.cxx
index ab47c849ce5c326f5a0c98899e7c1299ee1ab9dd..341d5f2c85f2386ab19c0115b313257d159d79c9 100644
--- a/Tracking/Acts/ActsDataPreparation/src/components/ActsDataPreparation_entries.cxx
+++ b/Tracking/Acts/ActsDataPreparation/src/components/ActsDataPreparation_entries.cxx
@@ -12,16 +12,22 @@
 #include "src/CoreStripSpacePointFormationTool.h"
 #include "src/StripSpacePointFormationTool.h"
 
-#include "src/CollectionDataPreparationAlg.h"
 #include "src/CacheCreator.h"
+#include "src/CollectionDataPreparationAlg.h"
+
 
 // Algs
 DECLARE_COMPONENT(ActsTrk::PixelClusterizationAlg)
 DECLARE_COMPONENT(ActsTrk::StripClusterizationAlg)
 DECLARE_COMPONENT(ActsTrk::PixelCacheClusterizationAlg)
 DECLARE_COMPONENT(ActsTrk::StripCacheClusterizationAlg)
+
 DECLARE_COMPONENT(ActsTrk::PixelSpacePointFormationAlg)
+DECLARE_COMPONENT(ActsTrk::PixelCacheSpacePointFormationAlg)
+
 DECLARE_COMPONENT(ActsTrk::StripSpacePointFormationAlg)
+DECLARE_COMPONENT(ActsTrk::StripCacheSpacePointFormationAlg)
+
 // Tools
 DECLARE_COMPONENT(ActsTrk::PixelClusteringTool)
 DECLARE_COMPONENT(ActsTrk::StripClusteringTool)
@@ -38,3 +44,4 @@ DECLARE_COMPONENT(ActsTrk::StripClusterDataPreparationAlg)
 DECLARE_COMPONENT(ActsTrk::SpacePointDataPreparationAlg)
 DECLARE_COMPONENT(ActsTrk::PixelClusterCacheDataPreparationAlg)
 DECLARE_COMPONENT(ActsTrk::StripClusterCacheDataPreparationAlg)
+DECLARE_COMPONENT(ActsTrk::SpacePointCacheDataPreparationAlg)
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/ClusterizationAlg.icc b/Tracking/Acts/ActsDataPreparation/src/details/ClusterizationAlg.icc
index e56b516c1652790965653d164862a047ad446501..af57d1d7f06e28499d4cfca0a0b2706c7c4d1674 100644
--- a/Tracking/Acts/ActsDataPreparation/src/details/ClusterizationAlg.icc
+++ b/Tracking/Acts/ActsDataPreparation/src/details/ClusterizationAlg.icc
@@ -101,7 +101,7 @@ StatusCode ClusterizationAlg<IClusteringTool, useCache>::execute(const EventCont
         }
       } // loop on ids
     } // loop on rois
-    
+ATH_MSG_DEBUG("Clusters produced size: "<<clusterContainer->size());    
     return StatusCode::SUCCESS;
 }
 
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/DataPreparationAlg.icc b/Tracking/Acts/ActsDataPreparation/src/details/DataPreparationAlg.icc
index 46af914c72858a45a1782d5ed12b824ce9c25d63..a591d8ab8147b1e9e6d1e5bae724f02aafdaed9c 100644
--- a/Tracking/Acts/ActsDataPreparation/src/details/DataPreparationAlg.icc
+++ b/Tracking/Acts/ActsDataPreparation/src/details/DataPreparationAlg.icc
@@ -2,6 +2,9 @@
   Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
+#include "xAODInDetMeasurement/ContainerAccessor.h"
+#include "AthenaMonitoringKernel/MonitoredTimer.h"
+
 namespace ActsTrk {
 
   template <typename external_collection_t, bool useCache>
@@ -130,9 +133,11 @@ namespace ActsTrk {
       //this function will wait if an item is not available
       auto ce = cacheHandle->indexFindPtr(idHash);
       if(ce == nullptr) continue;
-      
-      for(unsigned int i = ce->range_start; i < ce->range_end; i++){
-	outputCollection.push_back(ce->container->at(i));
+
+      for(auto rng: ce->ranges){
+        for(unsigned int i = rng.first; i < rng.second; i++){
+          outputCollection.push_back(ce->container->at(i));
+        }
       }
     }
     
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/PixelClusterCacheId.h b/Tracking/Acts/ActsDataPreparation/src/details/PixelClusterCacheId.h
new file mode 100644
index 0000000000000000000000000000000000000000..23b6f02d741f50eebdb0d2476853d458cb835977
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/PixelClusterCacheId.h
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ACTSTRK_PIXCLUSTERCACHEID_H
+#define ACTSTRK_PIXCLUSTERCACHEID_H
+
+#include "xAODInDetMeasurement/PixelCluster.h"
+#include "src/Cache.h"
+
+CLASS_DEF(ActsTrk::Cache::Handles<xAOD::PixelCluster>::IDCBackend, 70424203, 1);
+#endif
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.h b/Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fcc0b1f0eb864ab2548e418e0c6cd2f80a32b78
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.h
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ACTSTRK_DATAPREPARATION_PIXELSPACEPOINTFORMATIONALG_H
+#define ACTSTRK_DATAPREPARATION_PIXELSPACEPOINTFORMATIONALG_H
+
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaMonitoringKernel/GenericMonitoringTool.h"
+
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "StoreGate/ReadCondHandleKey.h"
+
+#include "ActsToolInterfaces/IPixelSpacePointFormationTool.h"
+
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+
+#include "xAODInDetMeasurement/PixelClusterContainer.h"
+#include "xAODInDetMeasurement/SpacePointContainer.h"
+#include "xAODInDetMeasurement/SpacePointAuxContainer.h"
+
+#include <string>
+
+#include "src/Cache.h"
+
+namespace ActsTrk {
+
+    /// @class PixelSpacePointFormationAlg
+    /// This version of PixelSpacePointFormationAlg uses xAOD pixel clusters
+    /// to find space points in the ITk pixeldetectors.
+    /// Pixel space points are obtained directly from the clusters,
+    /// with needed evaluation of the space point covariance terms
+    /// Space points are then recorded to storegate as ActsTrk::SpacePoint
+    /// into an ActsTrk::SpacePointContainer.
+    template <bool useCache>
+    class PixelSpacePointFormationAlgBase : public AthReentrantAlgorithm {
+    public:
+        /// @name AthReentrantAlgorithm methods
+        //@{
+        PixelSpacePointFormationAlgBase(const std::string& name,
+				    ISvcLocator* pSvcLocator);
+        virtual ~PixelSpacePointFormationAlgBase() = default;
+        virtual StatusCode initialize() override;
+        virtual StatusCode execute (const EventContext& ctx) const override;
+        //@}
+
+    private:
+        /// @name Disallow constructor without parameters, copy constructor, assignment operator
+        //@{
+        PixelSpacePointFormationAlgBase() = delete;
+        PixelSpacePointFormationAlgBase(const PixelSpacePointFormationAlgBase&) = delete;
+        PixelSpacePointFormationAlgBase &operator=(const PixelSpacePointFormationAlgBase&) = delete;
+        //@}
+
+        /// @name Input data using SG::ReadHandleKey
+        //@{
+        SG::ReadHandleKey<xAOD::PixelClusterContainer> m_pixelClusterContainerKey{this, "PixelClusters", "", "name of the input pixel cluster container"};
+        //@}
+
+        /// @name Input condition data using SG::ReadCondHandleKey
+        //@{
+        /// To get detector elements
+        SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_pixelDetEleCollKey{this, "PixelDetectorElements", "ITkPixelDetectorElementCollection", "Key of input SiDetectorElementCollection for Pixel"};
+        //@}
+
+        ///@name Output data using SG::WriteHandleKey
+        //@{
+	      SG::WriteHandleKey<xAOD::SpacePointContainer> m_pixelSpacePointContainerKey {this, "PixelSpacePoints", "", "name of the output pixel space point container"};
+        //@}
+
+        /// @name ToolHandle
+        //@{
+        /// For space point formation
+        ToolHandle<ActsTrk::IPixelSpacePointFormationTool> m_spacePointMakerTool{this, "SpacePointFormationTool", "", "Tool dedicated to the creation of pixel space points"};
+        /// For monitoring
+        ToolHandle<GenericMonitoringTool> m_monTool{this, "MonTool", "", "Monitoring tool"};
+        //@}
+
+        using Cache_IDC = typename Cache::Handles<xAOD::SpacePoint>::IDC;
+        using Cache_BackendUpdateHandleKey = typename Cache::Handles<xAOD::SpacePoint>::BackendUpdateHandleKey;
+        using Cache_BackendUpdateHandle = typename Cache::Handles<xAOD::SpacePoint>::BackendUpdateHandle;
+        using Cache_WriteHandleKey = typename Cache::Handles<xAOD::SpacePoint>::WriteHandleKey;
+        using Cache_WriteHandle = typename Cache::Handles<xAOD::SpacePoint>::WriteHandle;
+
+        Cache_WriteHandleKey m_SPCache{this,"SPCache",""};
+        Cache_BackendUpdateHandleKey m_SPCacheBackend{this,"SPCacheBackend",""};
+  };
+
+}
+
+#include "PixelSpacePointFormationAlgBase.icc"
+
+#endif // ACTSTRKSPACEPOINTFORMATION_PIXELSPACEPOINTFORMATIONALG_H
diff --git a/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.cxx b/Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.icc
similarity index 62%
rename from Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.cxx
rename to Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.icc
index 2a81b4ebe2eba3750e5149e071b7ab58289b9af1..5b014bebc57dd35492250280966502a09362e732 100644
--- a/Tracking/Acts/ActsDataPreparation/src/PixelSpacePointFormationAlg.cxx
+++ b/Tracking/Acts/ActsDataPreparation/src/details/PixelSpacePointFormationAlgBase.icc
@@ -1,9 +1,7 @@
 /*
-  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
-#include "PixelSpacePointFormationAlg.h"
-
 #include "InDetReadoutGeometry/SiDetectorElement.h"
 #include "PixelReadoutGeometry/PixelModuleDesign.h"
 
@@ -11,16 +9,20 @@
 
 #include "AthenaMonitoringKernel/Monitored.h"
 
+#include <optional>
+
 namespace ActsTrk {
 
   //------------------------------------------------------------------------
-  PixelSpacePointFormationAlg::PixelSpacePointFormationAlg(const std::string& name,
+  template <bool useCache>
+  PixelSpacePointFormationAlgBase<useCache>::PixelSpacePointFormationAlgBase(const std::string& name,
 							   ISvcLocator* pSvcLocator)
     : AthReentrantAlgorithm(name, pSvcLocator)
     {}
 
   //-----------------------------------------------------------------------
-  StatusCode PixelSpacePointFormationAlg::initialize()
+  template <bool useCache>
+  StatusCode PixelSpacePointFormationAlgBase<useCache>::initialize()
   {
     ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
 
@@ -32,11 +34,16 @@ namespace ActsTrk {
     if ( not m_monTool.empty() )
       ATH_CHECK( m_monTool.retrieve() );
 
+      //caching
+    ATH_CHECK(m_SPCache.initialize(useCache));
+    ATH_CHECK(m_SPCacheBackend.initialize(useCache));
+
     return StatusCode::SUCCESS;
   }
 
   //-------------------------------------------------------------------------
-  StatusCode PixelSpacePointFormationAlg::execute (const EventContext& ctx) const
+  template <bool useCache>
+  StatusCode PixelSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
   {
     auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
     auto nReceivedSPsPixel = Monitored::Scalar<int>( "numPixSpacePoints" , 0 );
@@ -55,6 +62,16 @@ namespace ActsTrk {
     ATH_CHECK(pixelSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
 					       std::make_unique<xAOD::SpacePointAuxContainer>() ));
     xAOD::SpacePointContainer *pixelSpacePoints = pixelSpacePointContainer.ptr();
+
+    Cache_WriteHandle cacheHandle;
+    if constexpr (useCache) {
+      cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
+      auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
+      ATH_CHECK(updateHandle.isValid());
+      ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
+      ATH_CHECK(cacheHandle.isValid());
+    }
+
     // Reserve space
     pixelSpacePoints->reserve(pixelClusters->size());
 
@@ -72,6 +89,8 @@ namespace ActsTrk {
       return StatusCode::FAILURE;
     }
 
+    
+
     // using trick for fast insertion
     std::vector< xAOD::SpacePoint* > preCollection;
     preCollection.reserve(pixelClusters->size());
@@ -79,19 +98,49 @@ namespace ActsTrk {
       preCollection.push_back( new xAOD::SpacePoint() );
     pixelSpacePoints->insert(pixelSpacePoints->end(), preCollection.begin(), preCollection.end());
 
-    /// production of ActsTrk::SpacePoint from pixel clusters
-    /// Pixel space points are created directly from the clusters global position
-    for (std::size_t idx(0); idx<inputPixelClusterContainer->size(); ++idx) {
-      auto cluster = inputPixelClusterContainer->at(idx);
-      const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(cluster->identifierHash());
+
+    std::map<IdentifierHash, std::vector<std::pair<unsigned int, unsigned int>>> cache_ranges;
+    int groupStartIdx = 0;
+    std::optional<IdentifierHash> groupIdHash = std::nullopt;
+    
+
+    for(unsigned int idx=0; idx<pixelClusters->size(); idx++){
+      const xAOD::PixelCluster* cluster = pixelClusters->at(idx);
+      IdentifierHash idHash = cluster->identifierHash();
+      if constexpr(useCache){
+        //check if the idHash is already in the cache
+        if(cacheHandle->tryAddFromCache(idHash)) continue;
+      }
+
+      const InDetDD::SiDetectorElement* pixelElement = pixelElements->getDetectorElement(idHash);
       if (pixelElement == nullptr) {
         ATH_MSG_FATAL("Element pointer is nullptr");
         return StatusCode::FAILURE;
       }
 
       ATH_CHECK( m_spacePointMakerTool->producePixelSpacePoint(*cluster,
-      							       *pixelSpacePoints->at(idx),
-      							       *pixelElement ) );
+                                *pixelSpacePoints->at(idx),
+                                *pixelElement ) );
+
+      if constexpr(useCache){
+        //check if the groupIdHash is defined if so and if it has changed then insert the range into the map
+        if(groupIdHash && ((*groupIdHash) != idHash)){
+          cache_ranges[idHash].emplace_back(groupStartIdx, idx);
+          groupStartIdx = idx;
+        }
+
+        groupIdHash = idHash;
+      }
+    }
+
+
+    if constexpr(useCache){
+      //add the ranges to the cache
+      for(auto idr: cache_ranges){
+        auto wh = cacheHandle->getWriteHandle(idr.first);
+        auto ce = std::make_unique<Cache::CacheEntry<xAOD::SpacePoint>>(pixelSpacePoints, idr.second);
+        ATH_CHECK(wh.addOrDelete(std::move(ce))); 
+      }
     }
 
     nReceivedSPsPixel = pixelSpacePointContainer->size();
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/SPCacheId.h b/Tracking/Acts/ActsDataPreparation/src/details/SPCacheId.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec027eb110ea5c326002b789e1bb60677d09408c
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/SPCacheId.h
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ACTSTRK_SPCACHEID_H
+#define ACTSTRK_SPCACHEID_H
+
+#include "xAODInDetMeasurement/SpacePoint.h"
+#include "src/Cache.h"
+
+CLASS_DEF(ActsTrk::Cache::Handles<xAOD::SpacePoint>::IDCBackend, 202232990, 1);
+#endif
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/StripClusterCacheId.h b/Tracking/Acts/ActsDataPreparation/src/details/StripClusterCacheId.h
new file mode 100644
index 0000000000000000000000000000000000000000..34bcdc6f71e9b6b8be8c525853e3f629966ed95d
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/StripClusterCacheId.h
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ACTSTRK_STRIPCLUSTERCACHEID_H
+#define ACTSTRK_STRIPCLUSTERCACHEID_H
+
+#include "xAODInDetMeasurement/StripCluster.h"
+#include "src/Cache.h"
+
+CLASS_DEF(ActsTrk::Cache::Handles<xAOD::StripCluster>::IDCBackend, 202232989, 1);
+#endif
\ No newline at end of file
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.h b/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b7a4f403c3fd7ec2f5e21de26102d96f944c064
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.h
@@ -0,0 +1,120 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ACTSTRK_DATAPREPARATION_StripSpacePointFormationAlgBase_H
+#define ACTSTRK_DATAPREPARATION_StripSpacePointFormationAlgBase_H
+
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaMonitoringKernel/GenericMonitoringTool.h"
+
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "StoreGate/ReadCondHandleKey.h"
+
+#include "ActsToolInterfaces/IStripSpacePointFormationTool.h"
+
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "SiSpacePointFormation/SiElementPropertiesTable.h"
+#include "BeamSpotConditionsData/BeamSpotData.h"
+
+#include "xAODInDetMeasurement/StripClusterContainer.h"
+#include "xAODInDetMeasurement/SpacePointContainer.h"
+#include "xAODInDetMeasurement/SpacePointAuxContainer.h"
+
+#include <string>
+
+#include "src/Cache.h"
+#include "SPCacheId.h"
+
+namespace ActsTrk {
+    /// @class StripSpacePointFormationAlgBase
+    /// This version of StripSpacePointFormationAlgBase uses xAOD strip clusters
+    /// to find space points in the ITk strip detectors.
+    /// Strip space points are made by combining clusters from pairs of
+    /// overlapping detectors. The access to overlapping detector elements is
+    /// possible using the ContainerAccessor.
+    /// The user can choose just to process the detector element and
+    /// its opposite on the stereo layer, or also to consider overlaps with the
+    /// four nearest neighbours of the opposite elements.
+    ///
+    /// Space points are then recorded to storegate as ActsTrk::SpacePoint
+    /// into an ActsTrk::SpacePointContainer.
+
+    template <bool useCache>
+    class StripSpacePointFormationAlgBase : public AthReentrantAlgorithm {
+    public:
+        /// @name AthReentrantAlgorithm methods
+        //@{
+        StripSpacePointFormationAlgBase(const std::string& name,
+				    ISvcLocator* pSvcLocator);
+        virtual ~StripSpacePointFormationAlgBase() = default;
+        virtual StatusCode initialize() override;
+        virtual StatusCode execute (const EventContext& ctx) const override;
+        //@}
+
+    private:
+        /// @name Disallow constructor without parameters, copy constructor, assignment operator
+        //@{
+        StripSpacePointFormationAlgBase() = delete;
+        StripSpacePointFormationAlgBase(const StripSpacePointFormationAlgBase&) = delete;
+        StripSpacePointFormationAlgBase &operator=(const StripSpacePointFormationAlgBase&) = delete;
+        //@}
+
+        /// @name Input data using SG::ReadHandleKey
+        //@{
+        SG::ReadHandleKey<xAOD::StripClusterContainer>  m_stripClusterContainerKey{this, "StripClusters", "", "name of the input strip cluster container"};
+        //@}
+
+        /// @name Input condition data using SG::ReadCondHandleKey
+        //@{
+        /// To get beam spot data
+        SG::ReadCondHandleKey<InDet::BeamSpotData> m_beamSpotKey { this, "BeamSpotKey", "BeamSpotData", "SG key for beam spot" };
+
+        /// To get detector elements
+        SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_stripDetEleCollKey{this, "StripDetectorElements", "ITkStripDetectorElementCollection", "Key of input SiDetectorElementCollection for Strip"};
+        /// To get strip module neighbours
+        SG::ReadCondHandleKey<InDet::SiElementPropertiesTable> m_stripPropertiesKey{this, "StripElementPropertiesTable", "ITkStripElementPropertiesTable", "Key of input SiElementPropertiesTable for Strip"};
+        //@}
+
+        ///@name Output data using SG::WriteHandleKey
+        //@{
+        SG::WriteHandleKey<xAOD::SpacePointContainer> m_stripSpacePointContainerKey{this, "StripSpacePoints", "", "name of the output strip space point container"};
+        SG::WriteHandleKey<xAOD::SpacePointContainer> m_stripOverlapSpacePointContainerKey{this, "StripOverlapSpacePoints", "", "name of the strip overlap strip space point container"};
+        //@}
+
+        /// @name ToolHandle
+        //@{
+        /// For space point formation
+        ToolHandle<ActsTrk::IStripSpacePointFormationTool> m_spacePointMakerTool{this, "SpacePointFormationTool", "", "Tool dedicated to the creation of pixel space points"};
+        /// For monitoring
+        ToolHandle<GenericMonitoringTool> m_monTool{this, "MonTool", "", "Monitoring tool"};
+        //@}
+
+        /// @name Configuration flags
+        //@{
+        Gaudi::Property< bool > m_processOverlapForStrip{this, "ProcessOverlapForStrip", true, "Enable production of eta/phi overlapping strip space points."};
+        //@}
+
+        //caching
+        using Cache_IDC = typename Cache::Handles<xAOD::SpacePoint>::IDC;
+        using Cache_BackendUpdateHandleKey = typename Cache::Handles<xAOD::SpacePoint>::BackendUpdateHandleKey;
+        using Cache_BackendUpdateHandle = typename Cache::Handles<xAOD::SpacePoint>::BackendUpdateHandle;
+        using Cache_WriteHandleKey = typename Cache::Handles<xAOD::SpacePoint>::WriteHandleKey;
+        using Cache_WriteHandle = typename Cache::Handles<xAOD::SpacePoint>::WriteHandle;
+
+        Cache_WriteHandleKey m_SPCache{this,"SPCache",""};
+        Cache_BackendUpdateHandleKey m_SPCacheBackend{this,"SPCacheBackend",""};
+
+        Cache_WriteHandleKey m_OSPCache{this,"OSPCache",""};
+        Cache_BackendUpdateHandleKey m_OSPCacheBackend{this,"OSPCacheBackend",""};
+
+        void fillSpacepoints(xAOD::SpacePointContainer* cont, std::vector<StripSP>& input, const xAOD::StripClusterContainer* inputClusters, unsigned int indexBase=0) const;
+  };
+
+}
+
+#include "StripSpacePointFormationAlgBase.icc"
+
+#endif // ACTSTRKSPACEPOINTFORMATION_StripSpacePointFormationAlgBase_H
diff --git a/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.icc b/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.icc
new file mode 100644
index 0000000000000000000000000000000000000000..36d95e11eef5cec50feead7dbf6a68ebec915979
--- /dev/null
+++ b/Tracking/Acts/ActsDataPreparation/src/details/StripSpacePointFormationAlgBase.icc
@@ -0,0 +1,244 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+
+#include "xAODInDetMeasurement/StripClusterAuxContainer.h"
+
+#include "AthenaMonitoringKernel/Monitored.h"
+#include "xAODInDetMeasurement/ContainerAccessor.h"
+
+namespace ActsTrk {
+
+  //------------------------------------------------------------------------
+  template <bool useCache>
+  StripSpacePointFormationAlgBase<useCache>::StripSpacePointFormationAlgBase(const std::string& name,
+							   ISvcLocator* pSvcLocator)
+    : AthReentrantAlgorithm(name, pSvcLocator)
+    {}
+
+  //-----------------------------------------------------------------------
+  template <bool useCache>
+  StatusCode StripSpacePointFormationAlgBase<useCache>::initialize()
+  {
+    ATH_MSG_DEBUG( "Initializing " << name() << " ... " );
+
+    ATH_CHECK( m_stripClusterContainerKey.initialize() );
+    ATH_CHECK( m_stripSpacePointContainerKey.initialize() );
+    ATH_CHECK( m_stripOverlapSpacePointContainerKey.initialize( m_processOverlapForStrip) );
+    ATH_CHECK( m_stripDetEleCollKey.initialize() );
+    ATH_CHECK( m_stripPropertiesKey.initialize() );
+
+    ATH_CHECK( m_beamSpotKey.initialize() );
+
+    if ( not m_monTool.empty() )
+      ATH_CHECK( m_monTool.retrieve() );
+
+    //caching
+    ATH_CHECK(m_SPCache.initialize(useCache));
+    ATH_CHECK(m_SPCacheBackend.initialize(useCache));
+    ATH_CHECK(m_OSPCache.initialize(useCache));
+    ATH_CHECK(m_OSPCacheBackend.initialize(useCache));
+
+    return StatusCode::SUCCESS;
+  }
+
+  //-------------------------------------------------------------------------
+  template <bool useCache>
+  StatusCode StripSpacePointFormationAlgBase<useCache>::execute (const EventContext& ctx) const
+  {
+    auto timer = Monitored::Timer<std::chrono::milliseconds>( "TIME_execute" );
+    auto nReceivedSPsStrip = Monitored::Scalar<int>( "numStripSpacePoints" , 0 );
+    auto nReceivedSPsStripOverlap = Monitored::Scalar<int>( "numStripOverlapSpacePoints" , 0 );
+    auto mon = Monitored::Group( m_monTool, timer, nReceivedSPsStrip, nReceivedSPsStripOverlap );
+
+    SG::ReadHandle<xAOD::StripClusterContainer> inputStripClusterContainer( m_stripClusterContainerKey, ctx );
+    if (!inputStripClusterContainer.isValid()){
+        ATH_MSG_FATAL("xAOD::StripClusterContainer with key " << m_stripClusterContainerKey.key() << " is not available...");
+        return StatusCode::FAILURE;
+    }
+    const xAOD::StripClusterContainer* inputClusters = inputStripClusterContainer.cptr();
+    ATH_MSG_DEBUG("Retrieved " << inputClusters->size() << " clusters from container " << m_stripClusterContainerKey.key());
+
+    
+    auto stripSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripSpacePointContainerKey, ctx );
+    ATH_MSG_DEBUG( "--- Strip Space Point Container `" << m_stripSpacePointContainerKey.key() << "` created ..." );
+    ATH_CHECK( stripSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
+						std::make_unique<xAOD::SpacePointAuxContainer>() ));
+    xAOD::SpacePointContainer* spacePoints = stripSpacePointContainer.ptr();
+
+    
+    xAOD::SpacePointContainer* overlapSpacePoints = nullptr;
+    SG::WriteHandle<xAOD::SpacePointContainer> stripOverlapSpacePointContainer;
+    if (m_processOverlapForStrip) {
+      stripOverlapSpacePointContainer = SG::WriteHandle<xAOD::SpacePointContainer>( m_stripOverlapSpacePointContainerKey, ctx );
+      ATH_MSG_DEBUG( "--- Strip Overlap Space Point Container `" << m_stripOverlapSpacePointContainerKey.key() << "` created ..." );
+      ATH_CHECK( stripOverlapSpacePointContainer.record( std::make_unique<xAOD::SpacePointContainer>(),
+							 std::make_unique<xAOD::SpacePointAuxContainer>() ));
+      overlapSpacePoints = stripOverlapSpacePointContainer.ptr();     
+    }
+
+    Cache_WriteHandle cacheHandle;
+    Cache_WriteHandle overlapCacheHandle;
+    if constexpr(useCache){
+      cacheHandle = Cache_WriteHandle(m_SPCache, ctx);
+      auto updateHandle = Cache_BackendUpdateHandle(m_SPCacheBackend, ctx);
+      ATH_CHECK(updateHandle.isValid());
+      ATH_CHECK(cacheHandle.record(std::make_unique<Cache_IDC>(updateHandle.ptr())));
+      ATH_CHECK(cacheHandle.isValid());
+
+      overlapCacheHandle = Cache_WriteHandle(m_OSPCache, ctx);
+      auto overlapUpdateHandle = Cache_BackendUpdateHandle(m_OSPCacheBackend, ctx);
+      ATH_CHECK(overlapUpdateHandle.isValid());
+      ATH_CHECK(overlapCacheHandle.record(std::make_unique<Cache_IDC>(overlapUpdateHandle.ptr())));
+      ATH_CHECK(overlapUpdateHandle.isValid());
+    }
+
+
+    // Early exit in case we have no clusters
+    // We still are saving an empty space point container in SG
+    if (inputClusters->empty()) {
+      ATH_MSG_DEBUG("No input clusters found, we stop space point formation");
+      return StatusCode::SUCCESS;
+    }
+
+    
+    SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle { m_beamSpotKey, ctx };
+    const InDet::BeamSpotData* beamSpot = *beamSpotHandle;
+    auto vertex = beamSpot->beamVtx().position();
+
+
+
+    SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> stripDetEleHandle(m_stripDetEleCollKey, ctx);
+    const InDetDD::SiDetectorElementCollection* stripElements(*stripDetEleHandle);
+    if (not stripDetEleHandle.isValid() or stripElements==nullptr) {
+      ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " is not available.");
+      return StatusCode::FAILURE;
+    }
+
+    SG::ReadCondHandle<InDet::SiElementPropertiesTable> stripProperties(m_stripPropertiesKey, ctx);
+    const InDet::SiElementPropertiesTable* properties = stripProperties.retrieve();
+    if (properties==nullptr) {
+      ATH_MSG_FATAL("Pointer of SiElementPropertiesTable (" << m_stripPropertiesKey.fullKey() << ") could not be retrieved");
+      return StatusCode::FAILURE;
+    }
+
+    ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1> clusterAccessor ( *inputClusters, [](const xAOD::StripCluster& cl) { return cl.identifierHash();}, stripElements->size());
+
+    if constexpr(useCache){
+      for(auto idHash: clusterAccessor.allIdentifiers()){
+        //obtain a write handle
+        auto cache_wh = cacheHandle->getWriteHandle(idHash);
+        auto overlap_cache_wh = overlapCacheHandle->getWriteHandle(idHash);
+        //check if already available
+        if(cache_wh.OnlineAndPresentInAnotherView()) continue;
+
+        unsigned int nsp = 0;
+
+        for(auto rng: clusterAccessor.rangesForIdentifierDirect(idHash)){
+          nsp += (rng.second - rng.first);
+        }
+
+        // Produce space points
+        std::vector<StripSP> sps;
+        std::vector<StripSP> osps;
+        //reserve the total number of clusters in the starting block
+        //at most will get one spacepoint for each
+        sps.reserve(nsp);
+        osps.reserve(nsp);
+
+        ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
+                  *inputClusters,
+                  *properties,
+                  *stripElements,
+                  vertex,
+                  sps,
+                  osps,
+                  m_processOverlapForStrip, 
+                  std::vector<IdentifierHash>{idHash}, 
+                  clusterAccessor) );
+
+        unsigned int sp_start_idx = spacePoints->size();
+
+        fillSpacepoints(spacePoints, sps, inputClusters, sp_start_idx);
+
+        //add to cache
+        ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(cache_wh, spacePoints, sp_start_idx, spacePoints->size()));
+
+        if(overlapSpacePoints && m_processOverlapForStrip){
+          unsigned int osp_start_idx = overlapSpacePoints->size();
+          fillSpacepoints(overlapSpacePoints, osps, inputClusters, osp_start_idx);
+
+          //add to cache
+          ATH_CHECK(Cache::Helper<xAOD::SpacePoint>::insert(overlap_cache_wh, overlapSpacePoints, osp_start_idx, overlapSpacePoints->size()));
+        }
+      }
+    }else{
+      // Produce space points without caching
+      std::vector<StripSP> sps;
+      std::vector<StripSP> osps;
+      sps.reserve(inputStripClusterContainer->size() * 0.5);
+      osps.reserve(inputStripClusterContainer->size() * 0.5);
+
+      ATH_CHECK( m_spacePointMakerTool->produceSpacePoints(ctx,
+                *inputClusters,
+                *properties,
+                *stripElements,
+                vertex,
+                sps,
+                osps,
+                m_processOverlapForStrip, 
+                clusterAccessor.allIdentifiers(), 
+                clusterAccessor) );
+
+      // using trick for fast insertion
+      spacePoints->reserve(sps.size());
+
+      fillSpacepoints(spacePoints, sps, inputClusters);
+
+      if(overlapSpacePoints && m_processOverlapForStrip){
+          overlapSpacePoints->reserve(osps.size());
+          fillSpacepoints(overlapSpacePoints, osps, inputClusters);
+      }
+    }
+
+    nReceivedSPsStrip = stripSpacePointContainer->size();
+    
+    nReceivedSPsStripOverlap = overlapSpacePoints->size();
+
+    return StatusCode::SUCCESS;
+  }
+
+  template <bool useCache>
+  void StripSpacePointFormationAlgBase<useCache>::fillSpacepoints(xAOD::SpacePointContainer* cont, std::vector<StripSP>& input, const xAOD::StripClusterContainer* inputClusters, unsigned int indexBase) const{
+      std::vector<xAOD::SpacePoint*> sp_collection;
+      sp_collection.reserve(input.size());
+      for (std::size_t i(0); i<input.size(); ++i)
+        sp_collection.push_back(new xAOD::SpacePoint());
+      cont->insert(cont->end(), sp_collection.begin(), sp_collection.end());
+
+      // fill
+      for (std::size_t i(0); i<input.size(); ++i) {
+        auto& toAdd = input.at(i);
+
+        // make link to Clusters
+        std::vector< const xAOD::UncalibratedMeasurement* > els(
+                      {inputClusters->at(toAdd.measurementIndexes[0]),
+                      inputClusters->at(toAdd.measurementIndexes[1])}
+                      );
+        cont->at(indexBase+i)->setSpacePoint(toAdd.idHashes, 
+            toAdd.globPos,
+            toAdd.cov_r,
+            toAdd.cov_z,
+            els,
+            toAdd.topHalfStripLength,
+            toAdd.bottomHalfStripLength,
+            toAdd.topStripDirection,
+            toAdd.bottomStripDirection,
+            toAdd.stripCenterDistance,
+            toAdd.topStripCenter);
+      }
+  }
+
+}
diff --git a/Tracking/Acts/ActsToolInterfaces/ActsToolInterfaces/IStripSpacePointFormationTool.h b/Tracking/Acts/ActsToolInterfaces/ActsToolInterfaces/IStripSpacePointFormationTool.h
index 344b63acfae4105703862214bc4bbadb59c69a3a..5a346e165eab0b8829a421a5b70ec44bbd6645bd 100644
--- a/Tracking/Acts/ActsToolInterfaces/ActsToolInterfaces/IStripSpacePointFormationTool.h
+++ b/Tracking/Acts/ActsToolInterfaces/ActsToolInterfaces/IStripSpacePointFormationTool.h
@@ -12,6 +12,7 @@
 #include "SiSpacePointFormation/SiElementPropertiesTable.h"
 #include "xAODInDetMeasurement/StripClusterContainer.h"
 #include "xAODInDetMeasurement/SpacePointContainer.h"
+#include "xAODInDetMeasurement/ContainerAccessor.h"
 
 namespace ActsTrk {
   struct StripSP {
@@ -45,7 +46,9 @@ namespace ActsTrk {
 					    const Amg::Vector3D& beamSpotVertex,
 					    std::vector<StripSP>& spacePoints,
 					    std::vector<StripSP>& overlapSpacePoints,
-					    bool processOverlaps) const = 0;
+					    bool processOverlaps,
+					    const std::vector<IdentifierHash>& hashesToProcess,
+					    ContainerAccessor<xAOD::StripCluster, IdentifierHash, 1>& stripAccessor) const = 0;
 
     };