diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
index e6d3326e85f99602098527c13550e626c368d7b1..648b819cc25f43378135568ea81dd082bf41fd3c 100644
--- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
+++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
@@ -5,11 +5,6 @@
 #include "AthenaKernel/errorcheck.h"
 #include "AthLinks/ElementLink.h"
 
-#define private public
-#   include "GeneratorObjects/McEventCollection.h"
-#undef private
-#include "GeneratorObjects/xAODTruthParticleLink.h"
-
 #include "GaudiKernel/MsgStream.h"
 #include "GaudiKernel/DataSvc.h"
 #include "GaudiKernel/PhysicalConstants.h"
@@ -46,30 +41,22 @@ namespace xAODMaker {
     xAODTruthCnvAlg::xAODTruthCnvAlg( const string& name, ISvcLocator* svcLoc )
     : AthAlgorithm( name, svcLoc ), m_metaStore( "MetaDataStore", name ), m_inputMetaStore( "StoreGateSvc/InputMetaDataStore",name)
     {
-        declareProperty("AODContainerName", m_aodContainerName="GEN_AOD" );
-        declareProperty("xAODTruthEventContainerName", m_xaodTruthEventContainerName="TruthEvents" );
-        declareProperty("xAODTruthPileupEventContainerName", m_xaodTruthPUEventContainerName="TruthPileupEvents" );
-        /// @todo TruthParticle -> TruthParticles
-        declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName="TruthParticles" );
-        /// @todo TruthVertex -> TruthVertices
-        declareProperty("xAODTruthVertexContainerName", m_xaodTruthVertexContainerName="TruthVertices" );
-        declareProperty("TruthLinks", m_truthLinkContainerName="xAODTruthLinks" );
         declareProperty( "WriteAllPileUpTruth", m_doAllPileUp = false);
         declareProperty( "WriteInTimePileUpTruth", m_doInTimePileUp = false);
         declareProperty( "MetaObjectName", m_metaName = "TruthMetaData" );
         declareProperty( "MetaDataStore", m_metaStore );
-        declareProperty( "ForceRerun", m_forceRerun = false);
+        declareProperty( "OnlyRedoLinks", m_onlyRedoLinks = false);
         declareProperty( "WriteTruthMetaData", m_writeMetaData = true);
     }
     
     
     StatusCode xAODTruthCnvAlg::initialize() {
         ATH_MSG_DEBUG("Initializing; package version: " << PACKAGE_VERSION );
-        ATH_MSG_DEBUG("AODContainerName = " << m_aodContainerName );
-        ATH_MSG_DEBUG("xAOD TruthEventContainer name = " << m_xaodTruthEventContainerName );
-        ATH_MSG_DEBUG("xAOD TruthPileupEventContainer name = " << m_xaodTruthPUEventContainerName );
-        ATH_MSG_DEBUG("xAOD TruthParticleContainer name = " << m_xaodTruthParticleContainerName );
-        ATH_MSG_DEBUG("xAOD TruthVertexContainer name = " << m_xaodTruthVertexContainerName );
+        ATH_MSG_DEBUG("AODContainerName = " << m_aodContainerKey.key() );
+        ATH_MSG_DEBUG("xAOD TruthEventContainer name = " << m_xaodTruthEventContainerKey.key() );
+        ATH_MSG_DEBUG("xAOD TruthPileupEventContainer name = " << m_xaodTruthPUEventContainerKey.key());
+        ATH_MSG_DEBUG("xAOD TruthParticleContainer name = " << m_xaodTruthParticleContainerKey.key() );
+        ATH_MSG_DEBUG("xAOD TruthVertexContainer name = " << m_xaodTruthVertexContainerKey.key() );
         if (m_doAllPileUp && m_doInTimePileUp) {
             ATH_MSG_FATAL( "Contradictory xAOD truth pile-up setting: all pile-up AND in-time alone requested simultaneously. Check settings." );
             return StatusCode::FAILURE;
@@ -77,6 +64,8 @@ namespace xAODMaker {
         if (m_doAllPileUp) ATH_MSG_INFO( "All pile-up truth (including out-of-time) will be written" );
         if (m_doInTimePileUp) ATH_MSG_INFO( "In-time pile-up truth (but not out-of-time) will be written" );
         if (!m_doAllPileUp && !m_doInTimePileUp) ATH_MSG_INFO( "No pile-up truth will be written" );
+
+        if (m_onlyRedoLinks) ATH_MSG_INFO( "Will only redo links, not full xAOD Truth." );
         
         if (m_writeMetaData) {
             CHECK( m_metaStore.retrieve() );
@@ -90,70 +79,70 @@ namespace xAODMaker {
             CHECK( m_metaStore->record( m_tmd, m_metaName ) );
         }
         
+	// initialize handles
+	ATH_CHECK(m_truthLinkContainerKey.initialize());
+
+	// if only redoing links
+	ATH_CHECK(m_linksOnlyTruthEventContainerKey.initialize(m_onlyRedoLinks));
+
+	// only if doing full truth
+	ATH_CHECK(m_aodContainerKey.initialize(!m_onlyRedoLinks));
+	ATH_CHECK(m_xaodTruthEventContainerKey.initialize(!m_onlyRedoLinks));
+	ATH_CHECK(m_xaodTruthPUEventContainerKey.initialize(!m_onlyRedoLinks && 
+							    (m_doAllPileUp || m_doInTimePileUp)));
+	ATH_CHECK(m_xaodTruthParticleContainerKey.initialize(!m_onlyRedoLinks));
+	ATH_CHECK(m_xaodTruthVertexContainerKey.initialize(!m_onlyRedoLinks));
+
         return StatusCode::SUCCESS;
     }
     
     
     StatusCode xAODTruthCnvAlg::execute() {
         
+	SG::WriteHandle<xAODTruthParticleLinkVector> truthLinkVec(m_truthLinkContainerKey);
+	ATH_CHECK(truthLinkVec.record(std::make_unique<xAODTruthParticleLinkVector>()));
         
-        // If the containers already exist then assume that nothing needs to be done
-        /// @todo Should this check be AND rather than OR? But pileup might be missing.
-        if ((evtStore()->contains< xAOD::TruthEventContainer >(m_xaodTruthEventContainerName) ||
-             evtStore()->contains< xAOD::TruthPileupEventContainer >(m_xaodTruthPUEventContainerName) ||
-             evtStore()->contains< xAOD::TruthParticleContainer >(m_xaodTruthParticleContainerName) ||
-             evtStore()->contains< xAOD::TruthVertexContainer >(m_xaodTruthVertexContainerName)) &&
-            !m_forceRerun) {
-            ATH_MSG_WARNING("xAOD Truth seems to be already available in the event");
-            return StatusCode::SUCCESS;
-        }
-        
-        xAODTruthParticleLinkVector* truthLinkVec = new xAODTruthParticleLinkVector();
-        CHECK( evtStore()->record( truthLinkVec, m_truthLinkContainerName ) );
-        
-        if (evtStore()->contains<McEventCollection>(m_aodContainerName)) {
-            
-            // Retrieve the HepMC truth:
-            const McEventCollection* mcColl = 0;
-            CHECK( evtStore()->retrieve( mcColl, m_aodContainerName ) );
-            ATH_MSG_DEBUG( "Retrieved HepMC with key: " << m_aodContainerName );
+        if (!m_onlyRedoLinks) {
             
+	    // Retrieve the HepMC truth:
+	    SG::ReadHandle<McEventCollection> mcColl(m_aodContainerKey);
+	    // validity check is only really needed for serial running. Remove when MT is only way.
+	    if (!mcColl.isValid()) {
+	      ATH_MSG_ERROR("Could not retrieve HepMC with key:" << m_aodContainerKey.key());
+	      return StatusCode::FAILURE;
+	    } else {
+	      ATH_MSG_DEBUG( "Retrieved HepMC with key: " << m_aodContainerKey.key() );
+	    }
+
             // **************************************************************
             // Create the xAOD containers and their auxiliary stores:
             // **************************************************************
             // Signal event
-            xAOD::TruthEventContainer* xTruthEventContainer = new xAOD::TruthEventContainer();
-            CHECK( evtStore()->record( xTruthEventContainer, m_xaodTruthEventContainerName ) );
-            xAOD::TruthEventAuxContainer* xTruthEventAuxContainer = new xAOD::TruthEventAuxContainer();
-            CHECK( evtStore()->record( xTruthEventAuxContainer, m_xaodTruthEventContainerName + "Aux." ) );
-            xTruthEventContainer->setStore( xTruthEventAuxContainer );
-            ATH_MSG_DEBUG( "Recorded TruthEventContainer with key: " << m_xaodTruthEventContainerName );
+            SG::WriteHandle<xAOD::TruthEventContainer> xTruthEventContainer(m_xaodTruthEventContainerKey);
+	    ATH_CHECK(xTruthEventContainer.record(std::make_unique<xAOD::TruthEventContainer>(),
+						  std::make_unique<xAOD::TruthEventAuxContainer>()));
+            ATH_MSG_DEBUG( "Recorded TruthEventContainer with key: " << m_xaodTruthEventContainerKey.key() );
+
             // Pile-up events
-            xAOD::TruthPileupEventContainer* xTruthPileupEventContainer = 0;
-            xAOD::TruthPileupEventAuxContainer* xTruthPileupEventAuxContainer = 0;
+            SG::WriteHandle<xAOD::TruthPileupEventContainer> xTruthPileupEventContainer;
             if (m_doAllPileUp || m_doInTimePileUp) {
-                xTruthPileupEventContainer = new xAOD::TruthPileupEventContainer();
-                CHECK( evtStore()->record( xTruthPileupEventContainer, m_xaodTruthPUEventContainerName ) );
-                xTruthPileupEventAuxContainer = new xAOD::TruthPileupEventAuxContainer();
-                CHECK( evtStore()->record( xTruthPileupEventAuxContainer, m_xaodTruthPUEventContainerName + "Aux." ) );
-                xTruthPileupEventContainer->setStore( xTruthPileupEventAuxContainer );
-                ATH_MSG_DEBUG( "Recorded TruthPileupEventContainer with key: " << m_xaodTruthPUEventContainerName );
+	      xTruthPileupEventContainer = SG::WriteHandle<xAOD::TruthPileupEventContainer>(m_xaodTruthPUEventContainerKey);
+	      ATH_CHECK(xTruthPileupEventContainer.record(std::make_unique<xAOD::TruthPileupEventContainer>(),
+							  std::make_unique<xAOD::TruthPileupEventAuxContainer>()));
+	      ATH_MSG_DEBUG( "Recorded TruthPileupEventContainer with key: " << m_xaodTruthPUEventContainerKey.key() );
             }
+
             // Particles
-            xAOD::TruthParticleContainer* xTruthParticleContainer = new xAOD::TruthParticleContainer();
-            CHECK( evtStore()->record( xTruthParticleContainer, m_xaodTruthParticleContainerName ) );
-            xAOD::TruthParticleAuxContainer* xTruthParticleAuxContainer = new xAOD::TruthParticleAuxContainer();
-            CHECK( evtStore()->record( xTruthParticleAuxContainer, m_xaodTruthParticleContainerName + "Aux." ) );
-            xTruthParticleContainer->setStore( xTruthParticleAuxContainer );
-            ATH_MSG_DEBUG( "Recorded TruthParticleContainer with key: " << m_xaodTruthParticleContainerName );
+            SG::WriteHandle<xAOD::TruthParticleContainer> xTruthParticleContainer(m_xaodTruthParticleContainerKey);
+	    ATH_CHECK(xTruthParticleContainer.record(std::make_unique<xAOD::TruthParticleContainer>(),
+						     std::make_unique<xAOD::TruthParticleAuxContainer>()));
+            ATH_MSG_DEBUG( "Recorded TruthParticleContainer with key: " << m_xaodTruthParticleContainerKey.key() );
             // Vertices
-            xAOD::TruthVertexContainer* xTruthVertexContainer = new xAOD::TruthVertexContainer();
-            CHECK( evtStore()->record( xTruthVertexContainer, m_xaodTruthVertexContainerName ) );
-            xAOD::TruthVertexAuxContainer* xTruthVertexAuxContainer = new xAOD::TruthVertexAuxContainer();
-            CHECK( evtStore()->record( xTruthVertexAuxContainer, m_xaodTruthVertexContainerName + "Aux." ) );
-            xTruthVertexContainer->setStore( xTruthVertexAuxContainer );
-            ATH_MSG_DEBUG( "Recorded TruthVertexContainer with key: " << m_xaodTruthVertexContainerName );
-            
+             SG::WriteHandle<xAOD::TruthVertexContainer> xTruthVertexContainer(m_xaodTruthVertexContainerKey);
+	    ATH_CHECK(xTruthVertexContainer.record(std::make_unique<xAOD::TruthVertexContainer>(),
+						     std::make_unique<xAOD::TruthVertexAuxContainer>()));
+            ATH_MSG_DEBUG( "Recorded TruthVertexContainer with key: " << m_xaodTruthVertexContainerKey.key() );
+             
             // ***********************************************************************************
             // Create the xAOD objects
             // This consists of three parts:
@@ -387,33 +376,33 @@ namespace xAODMaker {
                 
             } // end of loop over McEventCollection
             
-        } else {
-            
-            ATH_MSG_INFO("McEventCollection with name " << m_aodContainerName << " not found");
-            
-            // Retrieve the xAOD Truth and recreate the TruthLinks
-            if ( !evtStore()->contains<xAOD::TruthEventContainer>(m_xaodTruthEventContainerName) ) {
-                ATH_MSG_WARNING("TruthEventContainer " <<  m_xaodTruthEventContainerName << " not found");
-                return StatusCode::SUCCESS;
-            }
-            const xAOD::TruthEventContainer* xTruthEventContainer = 0;
-            CHECK( evtStore()->retrieve( xTruthEventContainer, m_xaodTruthEventContainerName ) );
-            
-            // Loop over events and particles
-            for (const xAOD::TruthEvent* evt : *xTruthEventContainer) {
-                for (const auto& par : evt->truthParticleLinks()) {
-                    if ( !par.isValid() ) {
-                        // This can happen if particles have been thinned.
-                        ATH_MSG_VERBOSE("Found invalid particle element link in TruthEvent"); //< @todo Use HepMC evt number?
-                        continue;
-                    }
-                    // Create link between HepMC and xAOD truth
-                    //truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), evt->eventNumber()), par));
-                    /// @todo AB: Truth particle links should only be made to the signal event... hence the 0. Right?
-                    truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), 0), par));
-                }
-            }
+        } else { // m_onlyRedoLinks
             
+	  SG::ReadHandle<xAOD::TruthEventContainer> xTruthEventContainer(m_linksOnlyTruthEventContainerKey);
+	  // validity check is only really needed for serial running. Remove when MT is only way.
+	  if (!xTruthEventContainer.isValid()) {
+	    ATH_MSG_ERROR("Could not retrieve xAOD::TruthEventContainer with key:" << 
+			  m_linksOnlyTruthEventContainerKey.key());
+	    return StatusCode::FAILURE;
+	  } else {
+	    ATH_MSG_DEBUG( "Retrieved for reading xAOD::TruthEventContainer key: " <<
+			   m_linksOnlyTruthEventContainerKey.key());
+	  }
+	  // Loop over events and particles
+	  for (const xAOD::TruthEvent* evt : *xTruthEventContainer) {
+	    for (const auto& par : evt->truthParticleLinks()) {
+	      if ( !par.isValid() ) {
+		// This can happen if particles have been thinned.
+		ATH_MSG_VERBOSE("Found invalid particle element link in TruthEvent"); //< @todo Use HepMC evt number?
+		continue;
+	      }
+	      // Create link between HepMC and xAOD truth
+	      //truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), evt->eventNumber()), par));
+	      /// @todo AB: Truth particle links should only be made to the signal event... hence the 0. Right?
+	      truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), 0), par));
+	    }
+	  }
+          
         }
         
         std::stable_sort(truthLinkVec->begin(), truthLinkVec->end(), SortTruthParticleLink());
diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
index 14448f519becf5cbd737704febdac8b31b1eb8f1..9c5a1d1ef830e8ea8f87660e39821d98c644ae9a 100644
--- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
+++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
@@ -7,10 +7,24 @@
 
 #include "AthenaBaseComps/AthAlgorithm.h"
 
+// The lines below I don't like. We should fix them when we update the
+// the metadata to handles (ATLASRECTS-4162).
+#define private public
+#   include "GeneratorObjects/McEventCollection.h"
+#undef private
+
+#include "GeneratorObjects/xAODTruthParticleLink.h"
+
 #include "xAODTruth/TruthEvent.h"
 #include "xAODTruth/TruthPileupEvent.h"
 #include "xAODTruth/TruthMetaDataContainer.h"
+#include "xAODTruth/TruthEventContainer.h"
+#include "xAODTruth/TruthPileupEventContainer.h"
+#include "xAODTruth/TruthParticleContainerFwd.h"
+#include "xAODTruth/TruthVertexContainerFwd.h"
 #include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
 
 #include <unordered_set>
 
@@ -58,14 +72,25 @@ namespace xAODMaker {
     static void fillParticle(xAOD::TruthParticle *tp, const HepMC::GenParticle *gp);
 
     /// The key of the input AOD truth container
-    std::string m_aodContainerName;
-
+    SG::ReadHandleKey<McEventCollection> m_aodContainerKey{ 
+      this, "AODContainerName", "GEN_AOD", "The input McEvenCollection"};
+    
     /// The key for the output xAOD truth containers
-    std::string m_xaodTruthEventContainerName;
-    std::string m_xaodTruthPUEventContainerName;
-    std::string m_xaodTruthParticleContainerName;
-    std::string m_xaodTruthVertexContainerName;
-    std::string m_truthLinkContainerName;
+    SG::WriteHandleKey<xAOD::TruthEventContainer> m_xaodTruthEventContainerKey{
+      this, "xAODTruthEventContainerName", "TruthEvents", "Output TruthEvents container"};
+    SG::WriteHandleKey<xAOD::TruthPileupEventContainer> m_xaodTruthPUEventContainerKey{
+      this, "xAODTruthPileupEventContainerName", "TruthPileupEvents", "Output TruthPileupEvents container"};
+    SG::WriteHandleKey<xAOD::TruthParticleContainer> m_xaodTruthParticleContainerKey{
+      this, "xAODTruthParticleContainerName", "TruthParticles", "Output TruthParticles container"};
+    SG::WriteHandleKey<xAOD::TruthVertexContainer> m_xaodTruthVertexContainerKey{
+      this, "xAODTruthVertexContainerName", "TruthVertices", "Output TruthVertices container"};
+    SG::WriteHandleKey<xAODTruthParticleLinkVector> m_truthLinkContainerKey{
+      this, "TruthLinks", "xAODTruthLinks", "Output xAODTruthLinks container"};
+
+    // if only redoing links 
+    SG::ReadHandleKey<xAOD::TruthEventContainer> m_linksOnlyTruthEventContainerKey{
+      this, "linksOnlyTruthEventContainerName", "TruthEvents", "Input TruthEvents container"};
+
     /// Pile-up options
     bool m_doAllPileUp;
     bool m_doInTimePileUp;
@@ -80,8 +105,8 @@ namespace xAODMaker {
     /// Set for tracking the mc channels for which we already added meta data 
     std::unordered_set<uint32_t> m_existingMetaDataChan;
 
-    /// a flag to force rerunning (useful for rerunning on ESDs)
-    bool m_forceRerun;
+    // to only redo links
+    bool m_onlyRedoLinks;
 
     /// option to disable writing of metadata (e.g. if running a filter on xAOD in generators)
     bool m_writeMetaData;
diff --git a/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py b/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py
index bb189f7129546eb72f8083ae8665151770222040..144c1b8de663cea957d94b5596b7d6b5cbc32db6 100755
--- a/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py
+++ b/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py
@@ -26,13 +26,14 @@ from McParticleAlgs.JobOptCfg import McAodBuilder,createMcAodBuilder,PileUpClass
 
 # If we're reprocessing, we may have TruthEvents but not xAODTruthLinks.
 # Remake the links here if needed.
+#   JM: In the future, this would not work. If TrutheEvents exists, it should
+#       be renamed out of the way. Force rerun is effectivly always true.
 # This needs to come before the McAodBuilder below; otherwise,
 # xAODTruthCnvAlg will also try to rebuild TruthEvents.
 if (objKeyStore.isInInput( "xAOD::TruthEventContainer", "TruthEvents" ) and
-      not objKeyStore.isInInput( "xAODTrigParticleLinkVector", "xAODTruthLinks" ) ):
+      not objKeyStore.isInInput( "xAODTruthParticleLinkVector", "xAODTruthLinks" ) ):
     from xAODTruthCnv.xAODTruthCnvConf import xAODMaker__xAODTruthCnvAlg
-    job += xAODMaker__xAODTruthCnvAlg("GEN_AOD2xAOD",
-                                      ForceRerun = True)
+    job += xAODMaker__xAODTruthCnvAlg("GEN_AOD2xAOD_links", OnlyRedoLinks = True)
 
 if (objKeyStore.isInInput( "McEventCollection", "TruthEvent" ) and 
     not objKeyStore.isInInput( "McEventCollection", "GEN_AOD" )):
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py b/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py
index 746f1e4201c6e632e6a3e4b10f1a4a539900e809..8dae9d81436b59b2c1baa1e48052844ee1486a08 100644
--- a/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py
@@ -10,9 +10,11 @@ from AthenaCommon.AppMgr import ServiceMgr as svcMgr
 StoreGateSvc=svcMgr.StoreGateSvc
 StoreGateSvc.AllowOverwrite=True
 
-# force the truth conversion to rerun, discussed in https://its.cern.ch/jira/browse/ATLASRECTS-2062
-if not globalflags.DataSource() == 'data':
-    topSequence.GEN_AOD2xAOD.ForceRerun=True
+# (JM) In release 22 ForceRerun is effectively always true. The configuration
+#      should add the alg if it needs to run, not if it doesn't
+# # force the truth conversion to rerun, discussed in https://its.cern.ch/jira/browse/ATLASRECTS-2062
+# if not globalflags.DataSource() == 'data':
+#     topSequence.GEN_AOD2xAOD.ForceRerun=True
 
 # include options 
 include("VrtSecInclusive/VrtSecInclusive_DV_postInclude.py")