diff --git a/algo/ca/core/tracking/CaFramework.h b/algo/ca/core/tracking/CaFramework.h
index 50e1a7069f01a47f4f1f27da8cc674198e2e93ec..9d9ec0488b9a6466dfb73b74effda4f4157a3289 100644
--- a/algo/ca/core/tracking/CaFramework.h
+++ b/algo/ca/core/tracking/CaFramework.h
@@ -226,7 +226,7 @@ namespace cbm::algo::ca
 
     TrackingMonitorData fMonitorData{};  ///< Tracking monitor data (statistics per call)
 
-    int fNofThreads = 1;  ///< Number of threads to execute the track-finder
+    int fNofThreads = 10;  ///< Number of threads to execute the track-finder
 
    public:
     Vector<CaHitTimeInfo> fHitTimeInfo;
@@ -243,11 +243,6 @@ namespace cbm::algo::ca
     Vector<Track> fRecoTracks{"Framework::fRecoTracks"};       ///< reconstructed tracks
     Vector<ca::HitIndex_t> fRecoHits{"Framework::fRecoHits"};  ///< packed hits of reconstructed tracks
 
-
-    // WARN: Potential race conditions ->
-    Vector<int> fHitKeyToTrack{"Framework::fHitKeyToTrack"};  // strip to track pointers
-
-
     fvec EventTime{0.f};
     fvec Err{0.f};
 
diff --git a/algo/ca/core/tracking/CaTrackFinder.cxx b/algo/ca/core/tracking/CaTrackFinder.cxx
index e7679e3efe809a3d45eb55a6fc2b1fb24c35b413..2dfedb8f9ae5cb4e402104574a6f1a5e4ee297c8 100644
--- a/algo/ca/core/tracking/CaTrackFinder.cxx
+++ b/algo/ca/core/tracking/CaTrackFinder.cxx
@@ -23,6 +23,7 @@
 #include "CaTrack.h"
 
 #include <chrono>
+#include <thread>
 
 using namespace cbm::algo::ca;
 
@@ -57,12 +58,15 @@ void TrackFinder::FindTracks()
   // ----- Reset data arrays -------------------------------------------------------------------------------------------
   frAlgo.fvHitKeyFlags.reset(frAlgo.fInputData.GetNhitKeys(), 0);
 
-  frAlgo.fRecoTracks.clear();
-  frAlgo.fRecoHits.clear();
-  frAlgo.fRecoHits.reserve(2 * frAlgo.fInputData.GetNhits());
-  frAlgo.fRecoTracks.reserve(2 * frAlgo.fInputData.GetNhits() / frAlgo.GetParameters().GetNstationsActive());
+  size_t nHitsExpected   = 2 * frAlgo.fInputData.GetNhits();
+  size_t nTracksExpected = 2 * frAlgo.fInputData.GetNhits() / frAlgo.GetParameters().GetNstationsActive();
 
   for (int iThread = 0; iThread < frAlgo.GetNofThreads(); ++iThread) {
+    fvRecoTracks[iThread].clear();
+    fvRecoTracks[iThread].reserve(nTracksExpected / frAlgo.GetNofThreads());
+    fvRecoHitIndices[iThread].clear();
+    fvRecoHitIndices[iThread].reserve(nHitsExpected / frAlgo.GetNofThreads());
+    frAlgo.fvTrackFinderWindow[iThread].InitTimeslice();
     for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); ++iS) {
       frAlgo.fvWData[iThread].TsHitIndices(iS).clear();
       frAlgo.fvWData[iThread].TsHitIndices(iS).reserve(frAlgo.fInputData.GetNhits());
@@ -70,7 +74,6 @@ void TrackFinder::FindTracks()
   }
 
   frAlgo.fvHitKeyFlags.reset(frAlgo.fInputData.GetNhitKeys(), 0);
-  frAlgo.fHitKeyToTrack.reset(frAlgo.fInputData.GetNhitKeys(), -1);
   frAlgo.fHitTimeInfo.reset(frAlgo.fInputData.GetNhits());
 
 
@@ -207,8 +210,32 @@ void TrackFinder::FindTracks()
               << fvWindowEndThread[iThread] / 1.e6 << " ms";
   }
 
-  for (int iThread = 0; iThread < frAlgo.GetNofThreads(); ++iThread) {
-    this->FindTracksThread(iThread);
+  // Save tracks
+  frAlgo.fRecoTracks.clear();
+  frAlgo.fRecoHits.clear();
+  if (frAlgo.GetNofThreads() == 1) {
+    this->FindTracksThread(0);
+    frAlgo.fRecoTracks = std::move(fvRecoTracks[0]);
+    frAlgo.fRecoHits   = std::move(fvRecoHitIndices[0]);
+  }
+  else {
+    std::vector<std::thread> vThreadList;
+    vThreadList.reserve(frAlgo.GetNofThreads());
+    for (int iTh = 0; iTh < frAlgo.GetNofThreads(); ++iTh) {
+      vThreadList.emplace_back(&TrackFinder::FindTracksThread, this, iTh);
+    }
+    for (auto& th: vThreadList) {
+      if (th.joinable()) { th.join(); }
+    }
+    auto Operation  = [](size_t acc, const Vector<auto>& v) { return acc + v.size(); };
+    int nRecoTracks = std::accumulate(fvRecoTracks.begin(), fvRecoTracks.end(), 0, Operation);
+    int nRecoHits   = std::accumulate(fvRecoHitIndices.begin(), fvRecoHitIndices.end(), 0, Operation);
+    frAlgo.fRecoTracks.reserve(nRecoTracks);
+    frAlgo.fRecoHits.reserve(nRecoHits);
+    for (int iTh = 0; iTh < frAlgo.GetNofThreads(); ++iTh) {
+      frAlgo.fRecoTracks.insert(frAlgo.fRecoTracks.end(), fvRecoTracks[iTh].begin(), fvRecoTracks[iTh].end()); 
+      frAlgo.fRecoHits.insert(frAlgo.fRecoHits.end(), fvRecoHitIndices[iTh].begin(), fvRecoHitIndices[iTh].end());  
+    }
   }
 
   frAlgo.fMonitorData.StopTimer(ETimer::FindTracks);
@@ -331,7 +358,7 @@ void TrackFinder::FindTracksThread(int iThread)
                   << statNwindowHits << " hits. "
                   << " Processing " << dataRead << " % of the TS time and "
                   << 100. * fvStatNhitsProcessed[iThread] / fStatNhitsTotal << " % of TS hits."
-                  << " Already reconstructed " << frAlgo.fRecoTracks.size() << " tracks ";
+                  << " Already reconstructed " << fvRecoTracks[iThread].size() << " tracks on thread #" << iThread;
       }
     }
 
@@ -389,14 +416,14 @@ void TrackFinder::FindTracksThread(int iThread)
         }
       }
       else {  // save the track
-        frAlgo.fRecoTracks.push_back(track);
+        fvRecoTracks[iThread].push_back(track);
         // mark the track hits as used
         for (int i = 0; i < track.fNofHits; i++) {
           int caHitId                        = frAlgo.fvWData[iThread].RecoHitIndex(trackFirstHit + i);
           const auto& h                      = frAlgo.fInputData.GetHit(caHitId);
           frAlgo.fvHitKeyFlags[h.FrontKey()] = 1;
           frAlgo.fvHitKeyFlags[h.BackKey()]  = 1;
-          frAlgo.fRecoHits.push_back(caHitId);
+          fvRecoHitIndices[iThread].push_back(caHitId);
         }
       }
       trackFirstHit += track.fNofHits;
@@ -421,12 +448,20 @@ void TrackFinder::Init()
   fvWindowEndThread.clear();
   fvStatNwindows.clear();
   fvStatNhitsProcessed.clear();
-
+  fvRecoTracks.clear();
+  fvRecoHitIndices.clear();
+  
   fvWindowStartThread.resize(frAlgo.GetNofThreads());
   fvWindowEndThread.resize(frAlgo.GetNofThreads());
   fvStatNwindows.resize(frAlgo.GetNofThreads());
   fvStatNhitsProcessed.resize(frAlgo.GetNofThreads());
+  fvRecoTracks.resize(frAlgo.GetNofThreads());
+  fvRecoHitIndices.resize(frAlgo.GetNofThreads());
 
+  for (int iThread = 0; iThread < frAlgo.GetNofThreads(); ++iThread) {
+    fvRecoTracks[iThread].SetName(std::string("TrackFinder::fvRecoTracks_") + std::to_string(iThread));
+    fvRecoHitIndices[iThread].SetName(std::string("TrackFinder::fvRecoHitIndices_") + std::to_string(iThread));
+  }
 
   fWindowLength = (ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) ? 500 : 10000;
 }
diff --git a/algo/ca/core/tracking/CaTrackFinder.h b/algo/ca/core/tracking/CaTrackFinder.h
index ba5eca97e06eb0d213c63a92419b4a8914577988..a8f33ab701376ca9f2841369dd6e97181e6cb0b5 100644
--- a/algo/ca/core/tracking/CaTrackFinder.h
+++ b/algo/ca/core/tracking/CaTrackFinder.h
@@ -70,6 +70,9 @@ namespace cbm::algo::ca
     std::vector<int> fvStatNwindows;
     std::vector<int> fvStatNhitsProcessed;
 
+    std::vector<Vector<Track>> fvRecoTracks;       ///< reconstructed tracks
+    std::vector<Vector<ca::HitIndex_t>> fvRecoHitIndices;  ///< packed hits of reconstructed tracks
+
     float fWindowLength  = 0.;
     float fWindowOverlap = 15.;  // ns
 
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.cxx b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
index f25135dc4c5ea703a04e6299231947a67c3cefb1..5e8f2676091102d6a8441263310984e6f093534f 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.cxx
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
@@ -119,6 +119,10 @@ bool TrackFinderWindow::checkTripletMatch(const ca::Triplet& l, const ca::Triple
   return true;
 }
 
+void TrackFinderWindow::InitTimeslice()
+{
+  fvHitKeyToTrack.reset(frAlgo.fInputData.GetNhitKeys(), -1);
+}
 
 // **************************************************************************************************
 // *                                                                                                *
@@ -428,8 +432,8 @@ void TrackFinderWindow::CaTrackFinderSlice()
       fvTrackCandidates.clear();
 
       for (const auto& h : frWData.Hits()) {
-        frAlgo.fHitKeyToTrack[h.FrontKey()] = -1;
-        frAlgo.fHitKeyToTrack[h.BackKey()]  = -1;
+        fvHitKeyToTrack[h.FrontKey()] = -1;
+        fvHitKeyToTrack[h.BackKey()]  = -1;
       }
 
       //== Loop over triplets with the required level, find and store track candidates
@@ -542,7 +546,7 @@ void TrackFinderWindow::CaTrackFinderSlice()
             const ca::Hit& h = frAlgo.fInputData.GetHit(hitId);
             bool isAlive     = true;
             {  // front  strip
-              auto& stripF = (frAlgo.fHitKeyToTrack)[h.FrontKey()];
+              auto& stripF = fvHitKeyToTrack[h.FrontKey()];
               if ((stripF >= 0) && (stripF != tr.Id())) {  // strip is used by other candidate
                 const auto& other = fvTrackCandidates[stripF];
                 if (!other.IsAlive() && tr.IsBetterThan(other)) {
@@ -561,7 +565,7 @@ void TrackFinderWindow::CaTrackFinderSlice()
             }
 
             {  // back strip
-              auto& stripB = (frAlgo.fHitKeyToTrack)[h.BackKey()];
+              auto& stripB = fvHitKeyToTrack[h.BackKey()];
               if ((stripB >= 0) && (stripB != tr.Id())) {  // strip is used by other candidate
                 const auto& other = fvTrackCandidates[stripB];
                 if (!other.IsAlive() && tr.IsBetterThan(other)) {
@@ -591,18 +595,18 @@ void TrackFinderWindow::CaTrackFinderSlice()
           tr.SetAlive(true);
           for (int iHit = 0; tr.IsAlive() && (iHit < (int) tr.Hits().size()); ++iHit) {
             const ca::Hit& h = frAlgo.fInputData.GetHit(tr.Hits()[iHit]);
-            tr.SetAlive(tr.IsAlive() && ((frAlgo.fHitKeyToTrack)[h.FrontKey()] == tr.Id())
-                        && ((frAlgo.fHitKeyToTrack)[h.BackKey()] == tr.Id()));
+            tr.SetAlive(tr.IsAlive() && (fvHitKeyToTrack[h.FrontKey()] == tr.Id())
+                        && (fvHitKeyToTrack[h.BackKey()] == tr.Id()));
           }
 
           if (!tr.IsAlive()) {  // release strips
             for (auto hitId : tr.Hits()) {
               const ca::Hit& h = frAlgo.fInputData.GetHit(hitId);
-              if (frAlgo.fHitKeyToTrack[h.FrontKey()] == tr.Id()) {
-                frAlgo.fHitKeyToTrack[h.FrontKey()] = -1;
+              if (fvHitKeyToTrack[h.FrontKey()] == tr.Id()) {
+                fvHitKeyToTrack[h.FrontKey()] = -1;
               }
-              if (frAlgo.fHitKeyToTrack[h.BackKey()] == tr.Id()) {
-                frAlgo.fHitKeyToTrack[h.BackKey()] = -1;
+              if (fvHitKeyToTrack[h.BackKey()] == tr.Id()) {
+                fvHitKeyToTrack[h.BackKey()] = -1;
               }
             }
           }
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.h b/algo/ca/core/tracking/CaTrackFinderWindow.h
index 2813e5ccc22e73344a0a03a3a27453ad823f71ee..b47eab980768024cf7493cd1921770ab5ddb65bd 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.h
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.h
@@ -60,6 +60,9 @@ namespace cbm::algo::ca
     void CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
                      unsigned char min_best_l, ca::Branch* new_tr);
 
+    /// \note The function initializes global arrays for a given thread
+    void InitTimeslice();
+
    private:
     ///-------------------------------
     /// Private methods
@@ -78,8 +81,11 @@ namespace cbm::algo::ca
     /// \note  The candidates may share any amount of hits.
     Vector<ca::Branch> fvTrackCandidates{"TrackFinderWindow::fTrackCandidates"};
 
-    Vector<int> fvHitFirstTriplet{"Framework::fHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
-    Vector<int> fvHitNofTriplets{"Framework::fHitNofTriplets"};    /// link hit ->n triplets { hit, *, *}
+    Vector<int> fvHitFirstTriplet{"TrackFinderWindow::fvHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
+    Vector<int> fvHitNofTriplets{"TrackFinderWindow::fvHitNofTriplets"};    /// link hit ->n triplets { hit, *, *}
+
+    /// \note Global array for a given thread
+    Vector<int> fvHitKeyToTrack{"TrackFinderWindow::fvHitKeyToTrack"};
 
     ca::Framework& frAlgo;                 ///< Reference to the main track finder algorithm class
     static constexpr bool fDebug = false;  // print debug info