diff --git a/MQ/mcbm/CbmDeviceEventBuilder.cxx b/MQ/mcbm/CbmDeviceEventBuilder.cxx
index 0ab84e439a2f4824015e46f369e2b36dc4da508d..3a2eef200f6c571f71d2eacedcae5b557290120b 100644
--- a/MQ/mcbm/CbmDeviceEventBuilder.cxx
+++ b/MQ/mcbm/CbmDeviceEventBuilder.cxx
@@ -23,6 +23,8 @@
 #include "FairMQLogger.h"
 #include "FairMQProgOptions.h"  // device->fConfig
 #include "FairParGenericSet.h"
+#include "FairRootFileSink.h"
+#include "FairRootManager.h"
 #include "FairRunOnline.h"
 
 #include "BoostSerializer.h"
@@ -59,6 +61,8 @@ try {
   //fbFillHistos      = fConfig->GetValue<bool>("FillHistos");
   //fbIgnoreTsOverlap = fConfig->GetValue<bool>("IgnOverMs");
 
+  fsOutputFileName = fConfig->GetValue<std::string>("OutFileName");  //For storage of events
+
   // Event builder algorithm params
   const std::vector<std::string> vsAddDet        = fConfig->GetValue<std::vector<std::string>>("AddDet");
   const std::vector<std::string> vsSetEvbuildWin = fConfig->GetValue<std::vector<std::string>>("SetEvbuildWin");
@@ -78,6 +82,31 @@ try {
   fdMinPublishTime = fConfig->GetValue<double_t>("PubTimeMin");
   fdMaxPublishTime = fConfig->GetValue<double_t>("PubTimeMax");
 
+  /// Prepare root output
+  if ("" != fsOutputFileName) {
+    fpRun         = new FairRunOnline();  // is this needed?
+    fpFairRootMgr = FairRootManager::Instance();
+    fpFairRootMgr->SetSink(new FairRootFileSink(fsOutputFileName));
+    if (nullptr == fpFairRootMgr->GetOutFile()) {
+      throw InitTaskError("Could not open root file");
+    }  // if( nullptr == fpFairRootMgr->GetOutFile() )
+  }    // if( "" != fsOutputFileName )
+  else {
+    throw InitTaskError("Empty output filename!");
+  }  // else of if( "" != fsOutputFileName )
+
+  LOG(info) << "Init Root Output to " << fsOutputFileName;
+  fpFairRootMgr->InitSink();
+
+  /// Create input vectors
+  fCbmTsEventHeader = new CbmTsEventHeader();
+  fpFairRootMgr->Register("EventHeader.", "Event", fCbmTsEventHeader, kTRUE);
+
+  /// Create storage vector for events
+  fEventsSel = new std::vector<CbmDigiEvent>();
+  fpFairRootMgr->RegisterAny("DigiEvent", fEventsSel, kTRUE);
+  fpFairRootMgr->WriteFolder();
+
   // Get the information about created channels from the device
   // Check if the defined channels from the topology (by name)
   // are in the list of channels which are possible/allowed
@@ -157,9 +186,6 @@ try {
 
     fEvbuildAlgo.SetTriggerWindow(selDet, dWinBeg, dWinEnd);
   }
-
-  /// Create input vectors
-  fCbmTsEventHeader = new CbmTsEventHeader();
 }
 catch (InitTaskError& e) {
   LOG(error) << e.what();
@@ -202,13 +228,12 @@ bool CbmDeviceEventBuilder::IsChannelNameAllowed(std::string channelName)
   return false;
 }
 
-
 // handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
 bool CbmDeviceEventBuilder::HandleData(FairMQParts& parts, int /*index*/)
 {
   fulNumMessages++;
-  LOG(debug) << "Received message number " << fulNumMessages << " with " << parts.Size() << " parts"
-             << ", size0: " << parts.At(0)->GetSize();
+  LOG(info) << "Received message number " << fulNumMessages << " with " << parts.Size() << " parts"
+            << ", size0: " << parts.At(0)->GetSize();
 
   if (0 == fulNumMessages % 10000) LOG(info) << "Received " << fulNumMessages << " messages";
 
@@ -216,7 +241,8 @@ bool CbmDeviceEventBuilder::HandleData(FairMQParts& parts, int /*index*/)
   uint32_t uPartIdx = 0;
 
   /// TS header
-  Deserialize<RootSerializer>(*parts.At(uPartIdx), fCbmTsEventHeader);
+  CbmTsEventHeader* evtHeader = new CbmTsEventHeader();
+  Deserialize<RootSerializer>(*parts.At(uPartIdx), evtHeader);
   ++uPartIdx;
 
   CbmDigiTimeslice ts;
@@ -279,16 +305,42 @@ bool CbmDeviceEventBuilder::HandleData(FairMQParts& parts, int /*index*/)
   LOG(debug) << "PSD Vector size: " << ts.fData.fPsd.fDigis.size();
 
   const std::vector<double> triggers = GetTriggerTimes(ts);
+  LOG(debug) << "triggers: " << triggers.size();
 
   /// Create events
   std::vector<CbmDigiEvent> vEvents = fEvbuildAlgo(ts, triggers);
+  LOG(debug) << "vEvents size: " << vEvents.size();
 
   /// Send events vector to ouput
-  if (!SendEvents(parts, vEvents)) return false;
+  if (!SendEvents(parts, vEvents)) { return false; }
+
+  /// Write events to file
+  (*fEventsSel) = std::move(vEvents);
+  LOG(debug) << "fEventSel size: " << fEventsSel->size();
+
+  // FIXME: poor man solution with lots of data copy until we undertand how to properly deal
+  /// with FairMq messages ownership and memory managment
+  (*fCbmTsEventHeader) = std::move(*evtHeader);
+
+  DumpTreeEntry();
 
   return true;
 }
 
+void CbmDeviceEventBuilder::DumpTreeEntry()
+{
+  // Unpacked digis + CbmEvent output to root file
+
+  /// FairRunOnline style
+  fpFairRootMgr->StoreWriteoutBufferData(fpFairRootMgr->GetEventTime());
+  fpFairRootMgr->FillEventHeader(fCbmTsEventHeader);
+  fpFairRootMgr->Fill();
+  fpFairRootMgr->DeleteOldWriteoutBufferData();
+
+  /// Clear event vector
+  fEventsSel->clear();
+}
+
 std::vector<double> CbmDeviceEventBuilder::GetTriggerTimes(const CbmDigiTimeslice& ts)
 {
   std::vector<double> vDigiTimes;
@@ -336,9 +388,7 @@ bool CbmDeviceEventBuilder::SendEvents(FairMQParts& partsIn, const std::vector<C
   oaEvt << vEvents;
   std::string* strMsgEvt = new std::string(ossEvt.str());
 
-  FairMQParts partsOut(std::move(partsIn));
-
-  partsOut.AddPart(NewMessage(
+  FairMQParts partsOut(NewMessage(
     const_cast<char*>(strMsgEvt->c_str()),  // data
     strMsgEvt->length(),                    // size
     [](void*, void* object) { delete static_cast<std::string*>(object); },
@@ -351,8 +401,26 @@ bool CbmDeviceEventBuilder::SendEvents(FairMQParts& partsIn, const std::vector<C
   return true;
 }
 
+void CbmDeviceEventBuilder::Finish()
+{
+  // Clean closure of output to root file
+  fpFairRootMgr->Write();
+  fpFairRootMgr->CloseSink();
+  fbFinishDone = kTRUE;
+}
+
 CbmDeviceEventBuilder::~CbmDeviceEventBuilder()
 {
+  /// Close things properly if not alredy done
+  if (!fbFinishDone) Finish();
+
+  /// Clear events vector
+  if (fEventsSel) {
+    fEventsSel->clear();
+    delete fEventsSel;
+  }
+  if (fpRun) { delete fpRun; }
+
   /// Clear metadata
   delete fCbmTsEventHeader;
 }
diff --git a/MQ/mcbm/CbmDeviceEventBuilder.h b/MQ/mcbm/CbmDeviceEventBuilder.h
index 2f4328ec4fdf2b2d4b2fdff0179270a8e8321b0c..d1dc5241f54912a5928ccf6170ac752d248748eb 100644
--- a/MQ/mcbm/CbmDeviceEventBuilder.h
+++ b/MQ/mcbm/CbmDeviceEventBuilder.h
@@ -30,6 +30,9 @@
 
 class CbmTsEventHeader;
 
+class FairRunOnline;
+class FairRootManager;
+
 class CbmDeviceEventBuilder : public FairMQDevice {
 public:
   CbmDeviceEventBuilder();
@@ -41,6 +44,8 @@ protected:
   bool HandleCommand(FairMQMessagePtr&, int);
 
 private:
+  Bool_t fbFinishDone = false;  //! Keep track of whether the Finish was already called
+
   /// Constants
 
   /// Control flags
@@ -50,6 +55,8 @@ private:
   /// User settings parameters
   /// Algo enum settings
   ECbmModuleId fTriggerDet = ECbmModuleId::kT0;
+
+  std::string fsOutputFileName = "";
   /// message queues
   std::string fsChannelNameDataInput   = "unpts_0";
   std::string fsChannelNameDataOutput  = "events";
@@ -89,6 +96,13 @@ private:
   /// TS information in header
   CbmTsEventHeader* fCbmTsEventHeader = nullptr;
 
+  /// Data storage
+  FairRunOnline* fpRun           = nullptr;
+  FairRootManager* fpFairRootMgr = nullptr;
+
+  /// CbmEvents
+  std::vector<CbmDigiEvent>* fEventsSel = nullptr;  //! output container of CbmEvents
+
   bool IsChannelNameAllowed(std::string channelName);
   bool SendEvents(FairMQParts& partsIn, const std::vector<CbmDigiEvent>& vEvents);
 
@@ -107,7 +121,8 @@ private:
   // Get detector type from string containing name
   ECbmModuleId GetDetectorId(std::string detName);
 
-  void Finish() {};
+  void DumpTreeEntry();
+  void Finish();
 };
 
 #endif /* CBMDEVICEEVENTBUILDER_H_ */
diff --git a/MQ/mcbm/runEventBuilder.cxx b/MQ/mcbm/runEventBuilder.cxx
index 9b5226374c143cb34e5dd4247ed5c5cf35638bde..0323efc9d8d675ffabf7848b0699b9e4fb56f93d 100644
--- a/MQ/mcbm/runEventBuilder.cxx
+++ b/MQ/mcbm/runEventBuilder.cxx
@@ -21,6 +21,8 @@ void addCustomOptions(bpo::options_description& options)
   options.add_options()("FillHistos", bpo::value<bool>()->default_value(true),
                         "Fill histograms and send them to histo server if true");
   options.add_options()("IgnTsOver", bpo::value<bool>()->default_value(false), "Ignore TS overlap if true");
+  options.add_options()("OutFileName", bpo::value<std::string>()->default_value("events.root"),
+                        "Name (full or relative path) of the output .root file ");
   options.add_options()("TriggerDet", bpo::value<std::string>()->default_value("kT0"),
                         "Set the trigger detector, use string matching an ECbmModuleId ");
   options.add_options()("AddDet", bpo::value<std::vector<std::string>>()->multitoken()->composing(),
diff --git a/MQ/mcbm/startEventBuilder.sh.in b/MQ/mcbm/startEventBuilder.sh.in
index d2c3936d39e88ac64235e4ee0d0954046377a38b..ea2028d8f9b2233da4de63d168dc493ca23eb974 100755
--- a/MQ/mcbm/startEventBuilder.sh.in
+++ b/MQ/mcbm/startEventBuilder.sh.in
@@ -171,6 +171,7 @@ while (( _iMoni < _nbmoni )); do
   EVTBUILDER+=" --PubTimeMin $_pubminsec"
   EVTBUILDER+=" --PubTimeMax $_pubmaxsec"
   EVTBUILDER+=" --FillHistos true"
+  EVTBUILDER+=" --OutFileName events.root"
   EVTBUILDER+=" --IgnTsOver false"
   EVTBUILDER+=" --TriggerDet kTof"
   EVTBUILDER+=" --TriggerWin 0.0"
@@ -202,7 +203,7 @@ while (( _iMoni < _nbmoni )); do
 
 done
 
-EVTSINK="DigiEventSink"
+EVTSINK="EventSink"
 EVTSINK+=" --id evtsink1"
 EVTSINK+=" --severity info"
 #EVTSINK+=" --severity debug"