diff --git a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
index 2228ea3f2506e720d7ca6409e2160138433e36a1..e6c1b294f051217e89761c085bf56910cf5dab29 100644
--- a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
+++ b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
@@ -22,7 +22,8 @@ atlas_add_component( TrigServices
                      ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} ${CORAL_LIBRARIES}
                      AthenaBaseComps AthenaInterprocess AthenaKernel AthenaMonitoringKernelLib AthenaPoolUtilities
                      ByteStreamCnvSvcBaseLib ByteStreamData EventInfoUtils GaudiKernel RDBAccessSvcLib StoreGateLib TrigKernel
-                     TrigDataAccessMonitoringLib TrigOutputHandlingLib TrigSteeringEvent TrigSteerMonitorLib xAODEventInfo xAODTrigger )
+                     TrigDataAccessMonitoringLib TrigOutputHandlingLib TrigSteeringEvent TrigSteerMonitorLib xAODEventInfo
+                     xAODTrigger TrigT1Result )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
index 19dbc13a7472f481ed3b458f52dcabd57d424607..4116772e05a08247e4ecbf981fc0344ba7d6454f 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
@@ -194,8 +194,9 @@ StatusCode HltEventLoopMgr::initialize()
   // HLTResultMT ReadHandle (created dynamically from the result builder property)
   m_hltResultRHKey = m_hltResultMaker->resultName();
   ATH_CHECK(m_hltResultRHKey.initialize());
-  // L1TriggerResult ReadHandle
-  ATH_CHECK(m_l1TriggerResultRHKey.initialize(m_rewriteLVL1.value()));
+  // L1TriggerResult and RoIBResult ReadHandles for RewriteLVL1
+  ATH_CHECK(m_l1TriggerResultRHKey.initialize(SG::AllowEmpty));
+  ATH_CHECK(m_roibResultRHKey.initialize(SG::AllowEmpty));
 
   ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
@@ -1286,24 +1287,48 @@ HltEventLoopMgr::DrainSchedulerStatusCode HltEventLoopMgr::drainScheduler()
 
     // Retrieve and convert the L1 result to the output data format
     IOpaqueAddress* l1addr = nullptr;
+    IOpaqueAddress* l1addrLegacy = nullptr;
     if (m_rewriteLVL1) {
-      auto l1TriggerResult = SG::makeHandle(m_l1TriggerResultRHKey, *thisFinishedEvtContext);
-      if (!l1TriggerResult.isValid()) markFailed();
-      HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result for RewriteLVL1",
-                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
-
-      DataObject* l1TriggerResultDO = m_evtStore->accessData(l1TriggerResult.clid(),l1TriggerResult.key());
-      if (l1TriggerResultDO == nullptr) markFailed();
-      HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result DataObject for RewriteLVL1",
-                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
-
-      sc = m_outputCnvSvc->createRep(l1TriggerResultDO,l1addr);
-      if (sc.isFailure()) {
-        delete l1addr;
-        atLeastOneFailed = true;
+      // Run-3 L1 simulation result
+      if (not m_l1TriggerResultRHKey.empty()) {
+        auto l1TriggerResult = SG::makeHandle(m_l1TriggerResultRHKey, *thisFinishedEvtContext);
+        if (!l1TriggerResult.isValid()) markFailed();
+        HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+        DataObject* l1TriggerResultDO = m_evtStore->accessData(l1TriggerResult.clid(),l1TriggerResult.key());
+        if (l1TriggerResultDO == nullptr) markFailed();
+        HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result DataObject for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+        sc = m_outputCnvSvc->createRep(l1TriggerResultDO,l1addr);
+        if (sc.isFailure()) {
+          delete l1addr;
+          atLeastOneFailed = true;
+        }
+        HLT_DRAINSCHED_CHECK(sc, "Conversion service failed to convert L1 Trigger Result for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+      }
+      // Legacy (Run-2) L1 simulation result
+      if (not m_roibResultRHKey.empty()) {
+        auto roibResult = SG::makeHandle(m_roibResultRHKey, *thisFinishedEvtContext);
+        if (!roibResult.isValid()) markFailed();
+        HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the RoIBResult for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+        DataObject* roibResultDO = m_evtStore->accessData(roibResult.clid(),roibResult.key());
+        if (roibResultDO == nullptr) markFailed();
+        HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the RoIBResult DataObject for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+        sc = m_outputCnvSvc->createRep(roibResultDO,l1addrLegacy);
+        if (sc.isFailure()) {
+          delete l1addrLegacy;
+          atLeastOneFailed = true;
+        }
+        HLT_DRAINSCHED_CHECK(sc, "Conversion service failed to convert RoIBResult for RewriteLVL1",
+                            HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
       }
-      HLT_DRAINSCHED_CHECK(sc, "Conversion service failed to convert L1 Trigger Result for RewriteLVL1",
-                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
     }
 
     // Save event processing time before sending output
@@ -1323,6 +1348,7 @@ HltEventLoopMgr::DrainSchedulerStatusCode HltEventLoopMgr::drainScheduler()
     // The output has been sent out, the ByteStreamAddress can be deleted
     delete addr;
     delete l1addr;
+    delete l1addrLegacy;
 
     //--------------------------------------------------------------------------
     // Flag idle slot to the timeout thread and reset the timer
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
index 22a0170ff789ac7014d6a564b2e021bedb012752..f26cc62fb393f12edb457123338e2c89ca21a3f5 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
@@ -12,6 +12,8 @@
 #include "TrigSteeringEvent/OnlineErrorCode.h"
 #include "TrigSteerMonitor/ISchedulerMonSvc.h"
 #include "TrigSteerMonitor/ITrigErrorMonTool.h"
+#include "TrigT1Result/RoIBResult.h"
+#include "xAODTrigger/TrigCompositeContainer.h"
 
 // Athena includes
 #include "AthenaBaseComps/AthService.h"
@@ -20,7 +22,6 @@
 #include "AthenaMonitoringKernel/Monitored.h"
 #include "CxxUtils/checker_macros.h"
 #include "xAODEventInfo/EventInfo.h"
-#include "xAODTrigger/TrigCompositeContainer.h"
 #include "StoreGate/ReadHandleKey.h"
 #include "StoreGate/WriteHandleKey.h"
 
@@ -259,7 +260,10 @@ private:
     this, "EventInfoRHKey", "EventInfo", "StoreGate key for reading xAOD::EventInfo"};
 
   SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_l1TriggerResultRHKey{
-    this, "L1TriggerResultRHKey", "L1TriggerResult", "StoreGate key for reading L1TriggerResult for RewriteLVL1"};
+    this, "L1TriggerResultRHKey", "", "StoreGate key for reading L1TriggerResult for RewriteLVL1"};
+
+  SG::ReadHandleKey<ROIB::RoIBResult> m_roibResultRHKey{
+    this, "RoIBResultRHKey", "", "StoreGate key for reading RoIBResult for RewriteLVL1 with legacy (Run-2) L1 simulation"};
 
   SG::ReadHandleKey<HLT::HLTResultMT> m_hltResultRHKey;    ///< StoreGate key for reading the HLT result
 
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py b/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
index 15043c2331cc2515c7d299298e159a5ffee15b95..cca5b80545594d0c8f38fc2c4b56b5272458f560 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
@@ -606,6 +606,10 @@ class rewriteLVL1(_modifier):
             # online
             from AthenaCommon.AppMgr import ServiceMgr as svcMgr
             svcMgr.HltEventLoopMgr.RewriteLVL1 = True
+            if ConfigFlags.Trigger.enableL1Phase1:
+                svcMgr.HltEventLoopMgr.L1TriggerResultRHKey = 'L1TriggerResult'
+            if ConfigFlags.Trigger.enableL1CaloLegacy or not ConfigFlags.Trigger.enableL1Phase1:
+                svcMgr.HltEventLoopMgr.RoIBResultRHKey = 'RoIBResult'
         else:
             # offline
             from AthenaCommon.AlgSequence import AthSequencer
@@ -613,13 +617,11 @@ class rewriteLVL1(_modifier):
             seq = AthSequencer('AthOutSeq')
             streamBS = findAlgorithm(seq, 'BSOutputStreamAlg')
             if ConfigFlags.Trigger.enableL1Phase1:
-                out_type = 'xAOD::TrigCompositeContainer'
-                out_name = 'L1TriggerResult'
-            else:
-                out_type = 'ROIB::RoIBResult'
-                out_name = 'RoIBResult'
-            streamBS.ExtraInputs += [ (out_type, 'StoreGateSvc+'+out_name) ]
-            streamBS.ItemList += [ out_type+'#'+out_name ]
+                streamBS.ExtraInputs += [ ('xAOD::TrigCompositeContainer', 'StoreGateSvc+L1TriggerResult') ]
+                streamBS.ItemList += [ 'xAOD::TrigCompositeContainer#L1TriggerResult' ]
+            if ConfigFlags.Trigger.enableL1CaloLegacy or not ConfigFlags.Trigger.enableL1Phase1:
+                streamBS.ExtraInputs += [ ('ROIB::RoIBResult', 'StoreGateSvc+RoIBResult') ]
+                streamBS.ItemList += [ 'ROIB::RoIBResult#RoIBResult' ]
 
 
 class writeBS(_modifier):