diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index 9e7f23db7eb3f749cecba0efae05fcd4ad236b5f..a70b0872c98516d229715c67c7f86b14d8102a83 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -165,6 +165,7 @@ set(SRCS
   kfp/KfpV0Finder.cxx
   kfp/KfpV0FinderChain.cxx
   kfp/KfpV0FinderConfig.cxx
+  kfp/KfpV0FinderQa.cxx
 )
 
 set(BUILD_INFO_CXX ${CMAKE_CURRENT_BINARY_DIR}/base/BuildInfo.cxx)
diff --git a/algo/base/Definitions.h b/algo/base/Definitions.h
index 6c6d77ba8715786fada47c3483207254bb269b49..b1ff4c9ccc8e804a33a67fe0ab40d81d74dd616e 100644
--- a/algo/base/Definitions.h
+++ b/algo/base/Definitions.h
@@ -78,6 +78,7 @@ namespace cbm::algo
     RecoTof,
     RecoFsd,
     Tracking,
+    V0Finder,
   };
 
 }  // namespace cbm::algo
@@ -148,7 +149,8 @@ CBM_ENUM_DICT(cbm::algo::QaStep,
   {"RecoMuch", cbm::algo::QaStep::RecoMuch},
   {"RecoTof", cbm::algo::QaStep::RecoTof},
   {"RecoFsd", cbm::algo::QaStep::RecoFsd},
-  {"Tracking", cbm::algo::QaStep::Tracking}
+  {"Tracking", cbm::algo::QaStep::Tracking},
+  {"V0Finder", cbm::algo::QaStep::V0Finder}
 );
 
 #endif
diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx
index b2a7355599cb93d886743aa37cd2accfbac6712e..f312ebaaab85e36f0a9c689883a4e9c09e8ca13e 100644
--- a/algo/global/Reco.cxx
+++ b/algo/global/Reco.cxx
@@ -275,7 +275,12 @@ void Reco::Init(const Options& opts)
     fTrackingEvent->SetContext(&fContext);
     fTrackingEvent->Init();
 
-    fV0Finder = std::make_unique<V0FinderChain>();
+    if (fQaManager != nullptr && Opts().Has(QaStep::V0Finder)) {
+      fV0Finder = std::make_unique<V0FinderChain>(fQaManager);
+    }
+    else {
+      fV0Finder = std::make_unique<V0FinderChain>();
+    }
     fV0Finder->SetContext(&fContext);
     fV0Finder->SetBmonDefinedAddresses(fBmonHitFinder->GetDiamondAddresses());
     fV0Finder->Init();
diff --git a/algo/kfp/KfpV0Finder.cxx b/algo/kfp/KfpV0Finder.cxx
index 2488ba89e29fcdcbdf690ed56c4e6ff7f20bf958..bc06d78009a0e876ea425d35df1249c3deb06f72 100644
--- a/algo/kfp/KfpV0Finder.cxx
+++ b/algo/kfp/KfpV0Finder.cxx
@@ -95,10 +95,10 @@ void V0Finder::CollectDca(const RecoResults& recoEvent)
       fEventMonitor.IncrementCounter(ECounter::TracksWoStsHits);
       continue;
     }
-    auto& particleInfo        = fvParticleInfo[iTrk];
-    auto [iPtFst, iHitFst]    = stsHitIndicesInTrack[0];
-    auto [iPtSnd, iHitSnd]    = stsHitIndicesInTrack[1];
-    fvParticleInfo[iTrk].fDca = EstimateDca(recoEvent.stsHits[iPtFst][iHitFst], recoEvent.stsHits[iPtSnd][iHitSnd]);
+    auto& particleInfo     = fvParticleInfo[iTrk];
+    auto [iPtFst, iHitFst] = stsHitIndicesInTrack[0];
+    auto [iPtSnd, iHitSnd] = stsHitIndicesInTrack[1];
+    particleInfo.fDca      = EstimateDca(recoEvent.stsHits[iPtFst][iHitFst], recoEvent.stsHits[iPtSnd][iHitSnd]);
     AssignPid(particleInfo);
   }
 }
diff --git a/algo/kfp/KfpV0Finder.h b/algo/kfp/KfpV0Finder.h
index 0272b0ab891d36253451c77bbf4e94a45d5bf8d6..72d1d1c579b7f4a40918dd58c1b5981a0179b7d2 100644
--- a/algo/kfp/KfpV0Finder.h
+++ b/algo/kfp/KfpV0Finder.h
@@ -36,6 +36,12 @@ namespace cbm::algo::kfp
       bool fbSelected{false};                                  //< The track was selected
     };
 
+    //* Framework and physical constants (public)
+    static constexpr double kPionMass{0.13957039};      ///< Pion mass [GeV/c2]
+    static constexpr double kProtonMass{0.938272088};   ///< Proton mass [GeV/c2]
+    static constexpr double kSpeedOfLight{29.9792458};  ///< Speed of light [cm/ns]
+    static constexpr int32_t kUndefPdg{-2};             ///< PDG for tracks, which PID cannot be inferred
+
     /// \brief Default constructor
     V0Finder() = default;
 
@@ -71,7 +77,7 @@ namespace cbm::algo::kfp
     const KFParticleFinder* GetKFParticleFinder() const { return fpTopoReconstructor->GetKFParticleFinder(); }
 
     /// \brief  Gets a vector of particle info
-    const std::vector<ParticleInfo> GetParticleInfo() const { return fvParticleInfo; }
+    const std::vector<ParticleInfo>& GetParticleInfo() const { return fvParticleInfo; }
 
     /// \brief  Gets selected t0
     /// \note   NaN, if Lambda-candidate was not found
@@ -83,6 +89,9 @@ namespace cbm::algo::kfp
     /// \brief  Gets found t0s
     const std::vector<double>& GetT0s() const { return fvT0s; }
 
+    /// \brief  Accessor to topology reconstructor
+    const std::unique_ptr<KFParticleTopoReconstructor>& GetTopoReconstructor() const { return fpTopoReconstructor; }
+
     /// \brief Initializes the instance (called in the beginning of the run)
     void Init();
 
@@ -226,12 +235,9 @@ namespace cbm::algo::kfp
     void SetKfpTrackParameters(KFPTrackVector& kfpTrkVector, uint32_t iKfpTrk, uint32_t iCaTrk,
                                const ca::Track::TrackParam_t& trkParam, const ParticleInfo& particleInfo) const;
 
-    //* Framework and physical constants
-    static constexpr double kPionMass{0.13957039};      ///< Pion mass [GeV/c2]
-    static constexpr double kProtonMass{0.938272088};   ///< Proton mass [GeV/c2]
-    static constexpr double kSpeedOfLight{29.9792458};  ///< Speed of light [cm/ns]
-    static constexpr int32_t kUndefPdg{-2};             ///< PDG for tracks, which PID cannot be inferred
-    static constexpr bool kUseAverageSpeed{false};      ///< If an average speed of tof hits is used
+
+    //* Framework and physical constants (private)
+    static constexpr bool kUseAverageSpeed{false};  ///< If an average speed of tof hits is used
 
     V0FinderMonitorData_t fEventMonitor;  ///< Main monitor data instance
 
diff --git a/algo/kfp/KfpV0FinderChain.cxx b/algo/kfp/KfpV0FinderChain.cxx
index f41a0597ac8adce96b374ee90e3ff00e02cdaf34..e23bc9e812d3bfd6357e011032e448830fd23c4d 100644
--- a/algo/kfp/KfpV0FinderChain.cxx
+++ b/algo/kfp/KfpV0FinderChain.cxx
@@ -18,6 +18,13 @@
 
 using cbm::algo::V0FinderChain;
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+V0FinderChain::V0FinderChain(const std::unique_ptr<qa::Manager>& qaManager)
+  : fpFinderQa(qaManager != nullptr ? std::make_unique<kfp::V0FinderQa>(qaManager, "V0Finder") : nullptr)
+{
+}
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 void V0FinderChain::Finalize() { L_(info) << fMonitorRun.ToString(); }
@@ -69,6 +76,8 @@ try {
   }
   const auto& pion{particles[iPion]};
   const auto& proton{particles[iProton]};
+  L_(info) << "!!!!!!!!!!! > pion:   " << pion.minDca;
+  L_(info) << "!!!!!!!!!!! > proton: " << proton.minDca;
 
   // ----- Define a BMON diamond
   if (fBmonDefinedAddresses.empty()) {
@@ -114,6 +123,11 @@ try {
     //* Init the V0 finder
     fFinder.Init();
   }
+
+  if (fpFinderQa != nullptr) {
+    fpFinderQa->Init();
+  }
+
   L_(info) << "kfp::V0FinderChain: initializing the V0-finder chain ... done";
 }
 catch (const std::exception& err) {
@@ -128,6 +142,9 @@ V0FinderChain::EventOutput V0FinderChain::ProcessEvent(const RecoResults& recoEv
   EventOutput res;
   res.triggers = fFinder.Process(recoEvent);
   res.monitor  = fFinder.GetEventMonitor();
+  if (fpFinderQa != nullptr) {
+    fpFinderQa->Exec(recoEvent, fFinder);
+  }
   fMonitorRun.AddMonitorData(res.monitor);
   return res;
 }
diff --git a/algo/kfp/KfpV0FinderChain.h b/algo/kfp/KfpV0FinderChain.h
index 630fc02e63e52d9e07dd89bf53669b3994224a0c..8053c93f79f686f5952542afa68e706a89c90f6d 100644
--- a/algo/kfp/KfpV0FinderChain.h
+++ b/algo/kfp/KfpV0FinderChain.h
@@ -15,6 +15,15 @@
 #include "global/RecoResults.h"
 #include "kfp/KfpV0Finder.h"
 #include "kfp/KfpV0FinderMonitor.h"
+#include "kfp/KfpV0FinderQa.h"
+
+namespace cbm::algo
+{
+  namespace qa
+  {
+    class Manager;
+  }
+}  // namespace cbm::algo
 
 namespace cbm::algo
 {
@@ -32,6 +41,10 @@ namespace cbm::algo
     /// \brief Default constructor
     V0FinderChain() = default;
 
+    /// \brief Constructor from parameters
+    /// \param pQaManager   A QA-manager
+    V0FinderChain(const std::unique_ptr<qa::Manager>& qaManager);
+
     /// \brief Copy constructor
     V0FinderChain(const V0FinderChain&) = delete;
 
@@ -61,8 +74,9 @@ namespace cbm::algo
     EventOutput ProcessEvent(const RecoResults& recoEvent);
 
    private:
-    kfp::V0Finder fFinder;                      ///< Instance of the V0-finding algorithm
-    kfp::V0FinderMonitor fMonitorRun;           ///< Monitor per run
-    PODVector<uint32_t> fBmonDefinedAddresses;  ///< Available addresses of BMON
+    kfp::V0Finder fFinder;                                 ///< Instance of the V0-finding algorithm
+    kfp::V0FinderMonitor fMonitorRun;                      ///< Monitor per run
+    std::unique_ptr<kfp::V0FinderQa> fpFinderQa{nullptr};  ///< QA module
+    PODVector<uint32_t> fBmonDefinedAddresses;             ///< Available addresses of BMON
   };
 }  // namespace cbm::algo
diff --git a/algo/kfp/KfpV0FinderQa.cxx b/algo/kfp/KfpV0FinderQa.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4239174a71b61b3df7b97fbeeda5fff6fabe8d1a
--- /dev/null
+++ b/algo/kfp/KfpV0FinderQa.cxx
@@ -0,0 +1,97 @@
+/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   KfpV0FinderQa.cxx
+/// \date   13.02.2025
+/// \brief  A V0 finding algorithm QA (implementation)
+/// \author Sergei Zharko <s.zharko@gsi.de>
+
+#include "kfp/KfpV0FinderQa.h"
+
+#include "global/RecoResults.h"
+#include "kfp/KfpV0Finder.h"
+
+
+using cbm::algo::kfp::V0FinderQa;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void V0FinderQa::Init()
+{
+  using qa::CanvasConfig;
+  using qa::H1D;
+  using qa::PadConfig;
+
+  //* Histogram initialisation
+  fvphMassLambdaCand =
+    MakeObj<H1D>("kfp_mass_lambda", "Mass of #Lambda-candidates;m [GeV/c^{2}];Counts", kMassB, kMassL, kMassU);
+  fvphMassAll    = MakeObj<H1D>("kfp_mass_all", "Mass of particles;m [GeV/c^{2}];Counts", 300, 0., 1.5);
+  fvphDcaAll     = MakeObj<H1D>("kfp_dca_all", "DCA of tracks to origin;DCA [cm];Counts", kDcaB, kDcaL, kDcaU);
+  fvphBetaAll    = MakeObj<H1D>("kfp_beta_all", "Speed of tracks;#beta;Counts", kBetaB, kBetaL, kBetaU);
+  fvphBetaPdg    = MakeObj<H1D>("kfp_beta_pdg", "Speed of tracks w/ PDG;#beta;Counts", kBetaB, kBetaL, kBetaU);
+  fvphBetaPion   = MakeObj<H1D>("kfp_beta_pion", "Speed of #pi-candidates;#beta;Counts", kBetaB, kBetaL, kBetaU);
+  fvphBetaProton = MakeObj<H1D>("kfp_beta_proton", "Speed of proton-candidates;#beta;Counts", kBetaB, kBetaL, kBetaU);
+
+  //* Canvas initialisation
+  auto canv = CanvasConfig("kfp_lambda", "Lambda-trigger summary QA", 4, 2);
+  canv.AddPadConfig(PadConfig(fvphMassLambdaCand, "hist"));  // (0, 0)
+  canv.AddPadConfig(PadConfig(fvphMassAll, "hist"));         // (1, 0)
+  canv.AddPadConfig(PadConfig(fvphDcaAll, "hist"));          // (0, 1)
+  canv.AddPadConfig(PadConfig(fvphBetaAll, "hist"));
+  canv.AddPadConfig(PadConfig(fvphBetaPdg, "hist"));
+  canv.AddPadConfig(PadConfig(fvphBetaPion, "hist"));
+  canv.AddPadConfig(PadConfig(fvphBetaProton, "hist"));
+  AddCanvasConfig(canv);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void V0FinderQa::Exec(const RecoResults& recoEvent, const V0Finder& v0Finder)
+{
+  //* Fill track distributions
+  const auto& tracks{recoEvent.tracks};
+  if (v0Finder.GetT0s().size() == 1) {
+    for (uint32_t iTrk = 0; iTrk < tracks.size(); ++iTrk) {
+      const auto& particleInfo{v0Finder.GetParticleInfo()[iTrk]};
+      bool bPdgDefined = (particleInfo.fPdg != V0Finder::kUndefPdg);
+      fvphDcaAll->Fill(bPdgDefined ? particleInfo.fDca : -999);
+      fvphBetaAll->Fill(particleInfo.fBeta);
+      if (bPdgDefined) {
+        fvphBetaPdg->Fill(particleInfo.fBeta);
+        if (particleInfo.fPdg == -211) {
+          fvphBetaPion->Fill(particleInfo.fBeta);
+        }
+        else if (particleInfo.fPdg == 2212) {
+          fvphBetaProton->Fill(particleInfo.fBeta);
+        }
+      }
+    }
+  }
+  else {
+    for (uint32_t iTrk = 0; iTrk < tracks.size(); ++iTrk) {
+      const auto& particleInfo{v0Finder.GetParticleInfo()[iTrk]};
+      bool bPdgDefined = (particleInfo.fPdg != V0Finder::kUndefPdg);
+      fvphDcaAll->Fill(bPdgDefined ? particleInfo.fDca : -999);
+      fvphBetaAll->Fill(-999);
+      if (bPdgDefined) {
+        fvphBetaPdg->Fill(-999);
+        if (particleInfo.fPdg == -211) {
+          fvphBetaPion->Fill(-999);
+        }
+        else if (particleInfo.fPdg == 2212) {
+          fvphBetaProton->Fill(-999);
+        }
+      }
+    }
+  }
+
+  //* Fill particle distributions
+  const auto& particles = v0Finder.GetTopoReconstructor()->GetParticles();
+  for (const auto& particle : particles) {
+    fvphMassAll->Fill(particle.GetMass());
+    if (particle.GetPDG() == 3122) {
+      fvphMassLambdaCand->Fill(particle.GetMass());
+    }
+  }
+}
diff --git a/algo/kfp/KfpV0FinderQa.h b/algo/kfp/KfpV0FinderQa.h
new file mode 100644
index 0000000000000000000000000000000000000000..39a1289bae0df797974d751642a59a8aa6b9b81f
--- /dev/null
+++ b/algo/kfp/KfpV0FinderQa.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   KfpV0FinderQa.h
+/// \date   13.02.2025
+/// \brief  A V0 finding algorithm QA
+/// \author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include "qa/QaTaskHeader.h"
+
+namespace cbm::algo
+{
+  class RecoResults;
+
+  namespace qa
+  {
+    class H1D;
+    class H2D;
+  }  // namespace qa
+
+  namespace kfp
+  {
+    class V0Finder;
+  }
+}  // namespace cbm::algo
+
+namespace cbm::algo::kfp
+{
+  /// \class V0FinderQa
+  /// \brief A QA-task for the V0-finding algorithm
+  class V0FinderQa : public qa::TaskHeader {
+   public:
+    /// \brief Constructor
+    /// \param pManager  Pointer to the QA manager
+    /// \param name      Name of the QA
+    V0FinderQa(const std::unique_ptr<qa::Manager>& pManager, std::string_view name) : qa::TaskHeader(pManager, name) {}
+
+    /// \brief Copy constructor
+    V0FinderQa(const V0FinderQa&) = delete;
+
+    /// \brief Move constructor
+    V0FinderQa(V0FinderQa&&) = delete;
+
+    /// \brief Copy assignment operator
+    V0FinderQa& operator=(const V0FinderQa&) = delete;
+
+    /// \brief Move assignment operator
+    V0FinderQa& operator=(V0FinderQa&&) = delete;
+
+    /// \brief Executes the task, fills the histograms
+    /// \param recoEvent  A reconstructed event instance
+    /// \param v0Finder   A V0-finder instance
+    void Exec(const RecoResults& recoEvent, const V0Finder& v0Finder);
+
+    /// \brief Initialized the task
+    void Init();
+
+   private:
+    //* Constants
+    static constexpr int kMassB    = 200;   ///< Lambda-candidate mass: number of bins
+    static constexpr double kMassL = 1.08;  ///< Lambda-candidate mass: lower bound [GeV/c2]
+    static constexpr double kMassU = 1.18;  ///< Lambda-candidate mass: upper bound [GeV/c2]
+    static constexpr int kDcaB     = 240;   ///< DCA to origin: number of bins
+    static constexpr double kDcaL  = 0.;    ///< DCA to origin: lower bound [cm]
+    static constexpr double kDcaU  = 12.;   ///< DCA to origin: upper bound [cm]
+    static constexpr int kBetaB    = 240;   ///< Speed of particle: number of bins
+    static constexpr double kBetaL = 0.;    ///< Speed of particle: lower bound [c]
+    static constexpr double kBetaU = 1.2;   ///< Speed of particle: upper bound [c]
+
+    //* Histograms
+    qa::H1D* fvphMassLambdaCand{nullptr};  ///< Mass of Lambda-candidates
+    qa::H1D* fvphMassAll{nullptr};         ///< Mass of all particles in the topology
+    qa::H1D* fvphDcaAll{nullptr};          ///< DCA of particles to origin
+    qa::H1D* fvphBetaAll{nullptr};         ///< Speed of all particles
+    qa::H1D* fvphBetaPdg{nullptr};         ///< Speed of particles with PID hypothesis
+    qa::H1D* fvphBetaPion{nullptr};        ///< Speed of pion-candidates
+    qa::H1D* fvphBetaProton{nullptr};      ///< Speed of proton-candidates
+  };
+}  // namespace cbm::algo::kfp
diff --git a/algo/qa/hitfind/BmonHitfindQa.h b/algo/qa/hitfind/BmonHitfindQa.h
index 020f62fa821a2c8ec298c8aa758684aee023cc21..b2a8b3e30e709d099ef1059aaa5a619864d02c54 100644
--- a/algo/qa/hitfind/BmonHitfindQa.h
+++ b/algo/qa/hitfind/BmonHitfindQa.h
@@ -34,8 +34,6 @@ namespace cbm::algo::bmon
 {
   /// \class HitfindQa
   /// \brief A QA module for the BMON hit-finder
-  /// \param pManager  Pointer to the QA manager
-  /// \param name      Name of the QA (directory)
   class HitfindQa : public qa::TaskHeader {
    public:
     /// \brief Constructor
@@ -44,7 +42,6 @@ namespace cbm::algo::bmon
     HitfindQa(const std::unique_ptr<qa::Manager>& pManager, std::string_view name) : qa::TaskHeader(pManager, name) {}
 
     /// \brief Constructor from the configuration object
-    /// \param config  QA configuration object
     HitfindQa() = default;
 
     /// \brief Copy constructor
diff --git a/services/histserv/app/Application.cxx b/services/histserv/app/Application.cxx
index 5eb5362f051fc3f34fc1108e50bd17e1adf6e4f2..d2215633eb84dbbad3eba51509872f4da98f08af 100644
--- a/services/histserv/app/Application.cxx
+++ b/services/histserv/app/Application.cxx
@@ -800,17 +800,21 @@ bool Application::PrepareCanvas(uint32_t uCanvIdx)
       if ("nullptr" != sName) {
         TObject* pObj = fArrayHisto[FindHistogram(sName)];
 
-        if (nullptr != dynamic_cast<TProfile2D*>(pObj)) {
-          dynamic_cast<TProfile2D*>(pObj)->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
+        if (auto* pHist = dynamic_cast<TProfile2D*>(pObj)) {
+          pHist->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
         }  // if( nullptr != dynamic_cast< TProfile *>( pObj ) )
-        else if (nullptr != dynamic_cast<TProfile*>(pObj)) {
-          dynamic_cast<TProfile*>(pObj)->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
+        else if (auto* pHist = dynamic_cast<TProfile*>(pObj)) {
+          pHist->SetLineColor(uObjIdx + 1);
+          pHist->SetMarkerColor(uObjIdx + 1);
+          pHist->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
         }  // if( nullptr != dynamic_cast< TProfile *>( pObj ) )
-        else if (nullptr != dynamic_cast<TH2*>(pObj)) {
-          dynamic_cast<TH2*>(pObj)->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
+        else if (auto* pHist = dynamic_cast<TH2*>(pObj)) {
+          pHist->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
         }  // if( nullptr != dynamic_cast< TH2 *>( pObj ) )
-        else if (nullptr != dynamic_cast<TH1*>(pObj)) {
-          dynamic_cast<TH1*>(pObj)->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
+        else if (auto* pHist = dynamic_cast<TH1*>(pObj)) {
+          pHist->SetLineColor(uObjIdx + 1);
+          pHist->SetMarkerColor(uObjIdx + 1);
+          pHist->Draw(conf.GetOption(uPadIdx, uObjIdx).data());
         }  // if( nullptr != dynamic_cast< TH1 *>( pObj ) )
         else
           LOG(warning) << "  Unsupported object type for " << sName << " when preparing canvas " << conf.GetName();