diff --git a/Tr/TrackExtrapolators/src/TrackStateProvider.cpp b/Tr/TrackExtrapolators/src/TrackStateProvider.cpp
index a15d2edcf9fcbd231388425c656b4209baf67ac7..0163b094ae2325cd2bd1d727315cab53f6ddc538 100644
--- a/Tr/TrackExtrapolators/src/TrackStateProvider.cpp
+++ b/Tr/TrackExtrapolators/src/TrackStateProvider.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************\
-* (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration      *
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
 *                                                                             *
 * This software is distributed under the terms of the GNU General Public      *
 * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
@@ -8,12 +8,9 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-// Include files
-// -------------
+
 // from Gaudi
 #include "GaudiAlg/GaudiTool.h"
-#include "GaudiKernel/IIncidentListener.h"
-#include "GaudiKernel/IIncidentSvc.h"
 #include "GaudiKernel/ToolHandle.h"
 
 // from TrackInterfaces
@@ -32,16 +29,16 @@
 #include "LHCbMath/Similarity.h"
 #include "TrackKernel/TrackTraj.h"
 
-// boost
-#include "boost/optional.hpp"
-//#include "boost/functional/hash.hpp"
-
 // STL
 #include <cstdint>
+#include <deque>
 #include <memory>
 #include <numeric>
 #include <unordered_map>
 
+// boost
+#include "boost/functional/hash.hpp"
+
 /** @class TrackStateProvider TrackStateProvider.h
  *
  *  A TrackStateProvider is a base class implementing methods
@@ -51,23 +48,93 @@
  *  @date   14/08/2010
  **/
 
-// forward declarations
 namespace {
-  class TrackCache;
-}
 
-class TrackStateProvider : public extends<GaudiTool, ITrackStateProvider, IIncidentListener> {
+  /// Type for cache key
+  using TkCacheKey = std::uintptr_t;
+
+  /// compare states by Z position
+  inline constexpr auto compareStateZ = []( const LHCb::State* lhs, const LHCb::State* rhs ) {
+    return lhs->z() < rhs->z();
+  };
+
+  /// Create the key for a given track
+  inline TkCacheKey trackID( const LHCb::Track& track ) {
+    TkCacheKey tkid = TkCacheKey( &track );
+    if ( track.fitResult() ) { boost::hash_combine( tkid, track.fitResult() ); }
+    if ( track.parent() ) { boost::hash_combine( tkid, track.parent() ); }
+    // How many IDs are needed to 'guarantee' uniqueness in hash ??
+    for ( const auto id : track.lhcbIDs() ) { boost::hash_combine( tkid, id.lhcbID() ); }
+    // if ( LIKELY( !track.lhcbIDs().empty() ) ) {
+    //  boost::hash_combine( tkid, track.lhcbIDs().front().lhcbID() );
+    //  boost::hash_combine( tkid, track.lhcbIDs().back().lhcbID() );
+    //}
+    return tkid;
+  }
+
+  // The TrackCache is basically just an 'extendable' TrackTraj
+  class TrackCache final : public LHCb::TrackTraj {
+
+  private:
+    const LHCb::Track*      m_track = nullptr;
+    std::deque<LHCb::State> m_ownedstates;
+    double                  m_zFirstMeasurement{-9999};
+
+  public:
+    /// Constructor from a track
+    TrackCache( const LHCb::Track& track ) : LHCb::TrackTraj( track ), m_track( &track ) {
+      const auto state    = track.stateAt( LHCb::State::Location::FirstMeasurement );
+      m_zFirstMeasurement = ( state ? state->z() : -9999 );
+    }
+
+    /// get the track
+    const LHCb::Track& track() const { return *m_track; }
+
+    /// return z position of state at first measurement
+    double zFirstMeasurement() const noexcept { return m_zFirstMeasurement; }
+
+    /// insert a new state in the container with states
+    const LHCb::State* insertState( std::ptrdiff_t pos, LHCb::State&& state );
+
+    /// return the states (work around keyword protected)
+    auto& states() noexcept { return refStates(); }
+
+    /// return the states (work around keyword protected)
+    const auto& states() const noexcept { return refStates(); }
+
+    /// return number of owned states
+    std::size_t numOwnedStates() const noexcept { return m_ownedstates.size(); }
+  };
+
+  const LHCb::State* TrackCache::insertState( std::ptrdiff_t pos, LHCb::State&& o_state ) {
+
+    // take ownership of state
+    auto& state = m_ownedstates.emplace_back( std::move( o_state ) );
+
+    // get the vector with states
+    auto& refstates = refStates();
+
+    // insert state
+    refstates.insert( std::next( refstates.begin(), pos ), &state );
+    assert( std::is_sorted( refstates.begin(), refstates.end(), compareStateZ ) );
+
+    // update the range of the trajectory
+    Trajectory::setRange( refstates.front()->z(), refstates.back()->z() );
+
+    // invalidate the cache
+    TrackTraj::invalidateCache();
+
+    return &state;
+  }
+
+} // namespace
+
+class TrackStateProvider : public extends<GaudiTool, ITrackStateProvider> {
 
 public:
   /// Standard constructor
   TrackStateProvider( const std::string& type, const std::string& name, const IInterface* parent );
 
-  /// initialize
-  StatusCode initialize() override;
-
-  /// initialize
-  StatusCode finalize() override;
-
   /// Compute the state of the track at position z.  The third
   /// argument is the tolerance: if an existing state is found within
   /// a z-distance 'tolerance', that state is returned.
@@ -85,48 +152,55 @@ public:
   }
 
   /// Retrieve the cached trajectory
-  const LHCb::TrackTraj* trajectory( const LHCb::Track& track ) const override;
+  const LHCb::TrackTraj* trajectory( const LHCb::Track& track ) const override { return &cache( track ); }
 
   /// Clear the cache
-  void clearCache() override;
+  void clearCache() const override;
 
   /// Clear the cache for a particular track
-  void clearCache( const LHCb::Track& track ) override;
-
-  /// incident service handle
-  void handle( const Incident& incident ) override;
+  void clearCache( const LHCb::Track& track ) const override;
 
 private:
-  /// Type for cache key
-  using TkCacheKey = std::uintptr_t;
-
-  StatusCode computeState( const TrackCache& tc, double z, LHCb::State& state,
-                           const LHCb::TrackTraj::StateContainer::const_iterator& position ) const;
+  /// Type for cache
+  using TrackCaches = std::unordered_map<TkCacheKey, TrackCache>;
 
-  const LHCb::State*
-  addState( TrackCache& tc, double z, LHCb::State::Location loc = LHCb::State::LocationUnknown,
-            boost::optional<LHCb::TrackTraj::StateContainer::const_iterator> position = boost::none ) const;
+private:
+  StatusCode computeState( const TrackCache& tc,    //
+                           const double      z,     //
+                           LHCb::State&      state, //
+                           std::ptrdiff_t    position ) const;
+
+  const LHCb::State* addState( TrackCache&           tc, //
+                               double                z,  //
+                               LHCb::State::Location loc      = LHCb::State::Location::LocationUnknown,
+                               std::ptrdiff_t        position = -1 ) const;
+
+  /// Get the track cache from the event store
+  TrackCaches& trackcache() const {
+    // auto* obj = m_caches.getIfExists();
+    // return const_cast<TrackCaches&>( obj ? *obj : *( m_caches.put( TrackCaches{} ) ) );
+    static constexpr auto loc = "TrackStateProviderCache";
+    using CacheTES            = AnyDataWrapper<TrackCaches>;
+    auto d                    = getIfExists<CacheTES>( loc );
+    if ( UNLIKELY( !d ) ) {
+      d = new CacheTES( TrackCaches{} );
+      put( d, loc );
+    }
+    return d->getData();
+  }
 
   /// Create a cache entry
-  std::unique_ptr<TrackCache> createCacheEntry( const TkCacheKey key, const LHCb::Track& track ) const;
+  TrackCache createCacheEntry( const TkCacheKey key, const LHCb::Track& track ) const;
 
   /// Retrieve a cache entry
   TrackCache& cache( const LHCb::Track& track ) const;
 
-  /// Create the key for a given track
-  inline TkCacheKey trackID( const LHCb::Track& track ) const {
-    // warn if operating on a track with no parent container.
-    if ( !track.parent() ) {
-      Error( "Track has no parent container. TrackStateProvider cache might be unreliable.." ).ignore();
-    }
-    // key is based on track memory addresses
-    return TkCacheKey( &track );
-  }
-
 private:
-  mutable std::unordered_map<TkCacheKey, std::unique_ptr<::TrackCache>> m_trackcache;
-  ToolHandle<ITrackExtrapolator>                                        m_extrapolator{"TrackMasterExtrapolator", this};
-  ToolHandle<ITrackInterpolator>                                        m_interpolator{"TrackInterpolator", this};
+  // mutable DataObjectHandle<AnyDataWrapper<TrackCaches>> m_caches{this, Gaudi::DataHandle::Writer, "CacheLocation",
+  //                                                               "TrackStateProviderCache"};
+
+  ToolHandle<ITrackExtrapolator> m_extrapolator{"TrackMasterExtrapolator", this};
+  ToolHandle<ITrackInterpolator> m_interpolator{"TrackInterpolator", this};
 
   Gaudi::Property<bool>   m_applyMaterialCorrections{this, "ApplyMaterialCorrections", true};
   Gaudi::Property<double> m_linearPropagationTolerance{this, "LinearPropagationTolerance", 1.0 * Gaudi::Units::mm};
@@ -135,159 +209,47 @@ private:
 
 /**********************************************************************************************/
 
-namespace {
-
-  constexpr struct compareStateZ_t {
-    bool operator()( const LHCb::State* lhs, const LHCb::State* rhs ) const { return lhs->z() < rhs->z(); }
-  } compareStateZ{};
-
-  // The TrackCache is basically just an 'extendable' TrackTraj
-  class TrackCache final : public LHCb::TrackTraj {
-
-  private:
-    const LHCb::Track*                        m_track = nullptr;
-    std::vector<std::unique_ptr<LHCb::State>> m_ownedstates;
-    double                                    m_zFirstMeasurement{-9999};
-
-  public:
-    TrackCache( const LHCb::Track& track ) : LHCb::TrackTraj( track ), m_track( &track ) {
-      const auto state    = track.stateAt( LHCb::State::FirstMeasurement );
-      m_zFirstMeasurement = ( state ? state->z() : -9999 );
-    }
-
-    /// get the track
-    const LHCb::Track& track() const { return *m_track; }
-
-    /// return z position of state at first measurement
-    double zFirstMeasurement() const noexcept { return m_zFirstMeasurement; }
-
-    // insert a new state in the container with states
-    const LHCb::State* insertState( StateContainer::const_iterator pos, std::unique_ptr<LHCb::State> state );
-
-    // return the states (work around keyword protected)
-    StateContainer& states() noexcept { return refStates(); }
-
-    // return the states (work around keyword protected)
-    const StateContainer& states() const noexcept { return refStates(); }
-
-    // return number of owned states
-    std::size_t numOwnedStates() const noexcept { return m_ownedstates.size(); }
-  };
-
-  /// Add a state
-  const LHCb::State* TrackCache::insertState( StateContainer::const_iterator pos,
-                                              std::unique_ptr<LHCb::State>   o_state ) {
-
-    // take ownership of state
-    m_ownedstates.push_back( std::move( o_state ) );
-    auto state = m_ownedstates.back().get();
-
-    // get the vector with states
-    StateContainer& refstates = refStates();
-
-    // temporary logic test
-    // if( refstates.size()>0) {
-    //       if(pos == refstates.end() ) {
-    // 	assert( refstates.back()->z() < state->z() ) ;
-    //       } else if ( pos == refstates.begin() ) {
-    // 	assert( refstates.front()->z() > state->z() ) ;
-    //       } else {
-    // 	StateContainer::iterator prev = pos ; --prev ;
-    // 	assert( (*prev)->z() < state->z() && state->z() < (*pos)->z() ) ;
-    //       }
-    //     }
-
-    // insert the state. gcc 4.8 has trouble with the
-    // const_iterator. let's hope that the optimization does the
-    // obvious with the following strange cast.
-    auto nonconstpos = refstates.begin() + std::distance( refstates.cbegin(), pos );
-    refstates.insert( nonconstpos, state );
-
-    // update the range of the trajectory
-    Trajectory::setRange( refstates.front()->z(), refstates.back()->z() );
-
-    // invalidate the cache
-    TrackTraj::invalidateCache();
-
-    return state;
-  }
-} // namespace
-
 DECLARE_COMPONENT( TrackStateProvider )
 
 //=============================================================================
 // TrackStateProvider constructor.
 //=============================================================================
-TrackStateProvider::TrackStateProvider( const std::string& type, const std::string& name, const IInterface* parent )
+TrackStateProvider::TrackStateProvider( const std::string& type, //
+                                        const std::string& name, //
+                                        const IInterface*  parent )
     : base_class( type, name, parent ) {
   declareProperty( "Extrapolator", m_extrapolator );
   declareProperty( "Interpolator", m_interpolator );
 }
 
 //=============================================================================
-// Initialization
-//=============================================================================
-StatusCode TrackStateProvider::initialize() {
-  StatusCode sc = GaudiTool::initialize();
-  // retrieve tools
-  if ( sc.isSuccess() ) sc = m_extrapolator.retrieve();
-  if ( sc.isSuccess() ) sc = m_interpolator.retrieve();
-  // reset at the start of each event
-  incSvc()->addListener( this, IncidentType::BeginEvent );
-  return sc;
-}
-
-//=============================================================================
-// Finalize
-//=============================================================================
-StatusCode TrackStateProvider::finalize() {
-  clearCache();
-  m_extrapolator.release().ignore();
-  m_interpolator.release().ignore();
-  return GaudiTool::finalize();
-}
-
-//=============================================================================
-// Incident handle
-//=============================================================================
-
-void TrackStateProvider::handle( const Incident& /* incident */ ) {
-  // only one incident type subscribed to, so no need to check type
-  // if ( IncidentType::BeginEvent == incident.type() )
-  clearCache();
-}
-
-//=============================================================================
-// Clear cache (and update some counters)
+// Clear cache
 //=============================================================================
-
-void TrackStateProvider::clearCache() {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Clearing cache. Size is " << m_trackcache.size() << "." << endmsg;
-  counter( "Number of tracks seen" ) += m_trackcache.size();
-  if ( !m_trackcache.empty() ) {
-    counter( "Number of states added" ) +=
-        std::accumulate( m_trackcache.begin(), m_trackcache.end(), 0,
-                         []( auto n, const auto& p ) { return n + p.second->numOwnedStates(); } );
-  }
-  m_trackcache.clear();
+void TrackStateProvider::clearCache() const {
+  auto& tc = trackcache();
+  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Clearing cache. Size is " << tc.size() << "." << endmsg; }
+  tc.clear();
 }
 
 //=============================================================================
 // Clear cache for a given track
 //=============================================================================
-
-void TrackStateProvider::clearCache( const LHCb::Track& track ) {
-  if ( msgLevel( MSG::DEBUG ) ) debug() << "Clearing cache for track: key=" << track.key() << endmsg;
-  auto it = m_trackcache.find( trackID( track ) );
-  if ( it != m_trackcache.end() ) m_trackcache.erase( it );
+void TrackStateProvider::clearCache( const LHCb::Track& track ) const {
+  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Clearing cache for track: key=" << track.key() << endmsg; }
+  auto& tc = trackcache();
+  auto  it = tc.find( trackID( track ) );
+  if ( it != tc.end() ) { tc.erase( it ); }
 }
 
 //=============================================================================
 // get a state at a particular z position, within given tolerance
 //=============================================================================
 
-StatusCode TrackStateProvider::state( LHCb::State& state, const LHCb::Track& track, double z,
-                                      double ztolerance ) const {
+StatusCode TrackStateProvider::state( LHCb::State&       state, //
+                                      const LHCb::Track& track, //
+                                      double             z,     //
+                                      double             ztolerance ) const {
+
   auto& tc = cache( track );
 
   // locate the closest state with lower_bound, but cache the
@@ -309,8 +271,11 @@ StatusCode TrackStateProvider::state( LHCb::State& state, const LHCb::Track& tra
   const auto absdz = std::abs( z - closeststate->z() );
   if ( absdz > std::max( ztolerance, TrackParameters::propagationTolerance ) ) {
     if ( absdz > m_linearPropagationTolerance ) {
-      if ( !m_cacheStatesOnDemand ) { return computeState( tc, z, state, position ); }
-      const auto newstate = addState( tc, z, LHCb::State::LocationUnknown, position );
+      if ( !m_cacheStatesOnDemand ) {
+        return computeState( tc, z, state, std::distance( tc.states().cbegin(), position ) );
+      }
+      const auto newstate =
+          addState( tc, z, LHCb::State::Location::LocationUnknown, std::distance( tc.states().cbegin(), position ) );
       counter( "AddedNumberOnDemandStates" ) += 1;
       if ( !newstate ) return StatusCode::FAILURE;
       state = *newstate;
@@ -329,42 +294,47 @@ StatusCode TrackStateProvider::state( LHCb::State& state, const LHCb::Track& tra
 // add a state to the cache of a given track
 //=============================================================================
 
-const LHCb::State*
-TrackStateProvider::addState( TrackCache& tc, double z, LHCb::State::Location loc,
-                              boost::optional<LHCb::TrackTraj::StateContainer::const_iterator> position ) const {
-  auto state = std::make_unique<LHCb::State>( loc );
-  state->setZ( z );
-  auto       it = ( position ? *position
-                       : std::lower_bound( tc.states().cbegin(), tc.states().cend(), state.get(), compareStateZ ) );
-  const auto sc = computeState( tc, z, *state, it );
+const LHCb::State* TrackStateProvider::addState( TrackCache& tc, double z, LHCb::State::Location loc,
+                                                 std::ptrdiff_t position ) const {
+  auto state = LHCb::State{loc};
+  state.setZ( z );
+  if ( position < 0 ) {
+    position = std::distance( tc.states().cbegin(),
+                              std::lower_bound( tc.states().cbegin(), tc.states().cend(), &state, compareStateZ ) );
+  }
+  const auto sc = computeState( tc, z, state, position );
   if ( !sc ) return nullptr;
-  state->setLocation( loc );
+  state.setLocation( loc );
   if ( msgLevel( MSG::DEBUG ) ) {
     debug() << "Adding state to track cache: key=" << tc.track().key() << " " << z << " " << loc << endmsg;
   }
-  return tc.insertState( it, std::move( state ) );
+  return tc.insertState( position, std::move( state ) );
 }
 
-StatusCode TrackStateProvider::computeState( const TrackCache& tc, double z, LHCb::State& state,
-                                             const LHCb::TrackTraj::StateContainer::const_iterator& position ) const {
+StatusCode TrackStateProvider::computeState( const TrackCache& tc,    //
+                                             const double      z,     //
+                                             LHCb::State&      state, //
+                                             std::ptrdiff_t    position ) const {
   // in brunel, we simply use the interpolator. in davinci, we use the
   // extrapolator, and we take some control over material corrections.
   const auto& track = tc.track();
-  if ( track.fitResult() && !track.fitResult()->nodes().empty() && track.fitStatus() == LHCb::Track::Fitted ) {
+  const auto* fit   = track.fitResult();
+  if ( fit && !fit->nodes().empty() && track.fitStatus() == LHCb::Track::FitStatus::Fitted ) {
     return m_interpolator->interpolate( track, z, state );
   }
 
   // locate the states surrounding this z position
   const auto& refstates = tc.states();
   state.setZ( z );
-  auto it                       = position;
+  auto it                       = std::next( refstates.begin(), position );
   bool applyMaterialCorrections = false;
   if ( it == refstates.end() ) {
     state = *refstates.back();
   } else if ( it == refstates.begin() || z < tc.zFirstMeasurement() ) {
     state = **it;
     // if we extrapolate from ClosestToBeam, we don't apply mat corrections.
-    applyMaterialCorrections = ( state.location() != LHCb::State::ClosestToBeam && m_applyMaterialCorrections );
+    applyMaterialCorrections =
+        ( state.location() != LHCb::State::Location::ClosestToBeam && m_applyMaterialCorrections );
   } else {
     // take the closest state.
     auto prev = std::prev( it );
@@ -377,10 +347,12 @@ StatusCode TrackStateProvider::computeState( const TrackCache& tc, double z, LHC
 
   LHCb::StateVector  statevec( state.stateVector(), state.z() );
   Gaudi::TrackMatrix transmat;
-  auto               sc = m_extrapolator->propagate( statevec, z, &transmat );
-  state.setState( statevec );
-  state.setCovariance( LHCb::Math::Similarity( transmat, state.covariance() ) );
 
+  auto sc = m_extrapolator->propagate( statevec, z, &transmat );
+  if ( LIKELY( sc.isSuccess() ) ) {
+    state.setState( statevec );
+    state.setCovariance( LHCb::Math::Similarity( transmat, state.covariance() ) );
+  }
   return sc;
 }
 
@@ -388,27 +360,29 @@ StatusCode TrackStateProvider::computeState( const TrackCache& tc, double z, LHC
 // retrieve the cache for a given track
 //=============================================================================
 
-std::unique_ptr<TrackCache> TrackStateProvider::createCacheEntry( TkCacheKey key, const LHCb::Track& track ) const {
-  if ( msgLevel( MSG::DEBUG ) )
+TrackCache TrackStateProvider::createCacheEntry( TkCacheKey key, const LHCb::Track& track ) const {
+
+  if ( msgLevel( MSG::DEBUG ) ) {
     debug() << "Creating track cache for track: key=" << track.key() << " hashID=" << key << " "
             << track.states().size() << endmsg;
+  }
 
   // create a new entry in the cache
-  auto tc = std::make_unique<TrackCache>( track );
+  TrackCache tc{track};
 
   // make sure downstream tracks have a few ref states before the first measurement.
-  if ( track.type() == LHCb::Track::Downstream ) {
-    for ( const auto& loc : {std::make_pair( LHCb::State::EndRich1, StateParameters::ZEndRich1 ),
-                             std::make_pair( LHCb::State::BegRich1, StateParameters::ZBegRich1 ),
-                             std::make_pair( LHCb::State::EndVelo, StateParameters::ZEndVelo )} ) {
-      if ( !track.stateAt( loc.first ) ) { addState( *tc, loc.second, loc.first ); }
+  if ( track.type() == LHCb::Track::Types::Downstream ) {
+    for ( const auto& loc : {std::pair{LHCb::State::Location::EndRich1, StateParameters::ZEndRich1},
+                             std::pair{LHCb::State::Location::BegRich1, StateParameters::ZBegRich1},
+                             std::pair{LHCb::State::Location::EndVelo, StateParameters::ZEndVelo}} ) {
+      if ( !track.stateAt( loc.first ) ) { addState( tc, loc.second, loc.first ); }
     }
   }
 
   // make sure all tracks (incl. Downstream) get assigned a state at
   // the beamline. this is useful for the trajectory approximation.
-  if ( ( track.hasVelo() || track.hasTT() ) && track.firstState().location() != LHCb::State::ClosestToBeam &&
-       !track.stateAt( LHCb::State::ClosestToBeam ) ) {
+  if ( ( track.hasVelo() || track.hasTT() ) && track.firstState().location() != LHCb::State::Location::ClosestToBeam &&
+       !track.stateAt( LHCb::State::Location::ClosestToBeam ) ) {
     // compute poca of first state with z-axis
     const auto& vec = track.firstState().stateVector();
     // check on division by zero (track parallel to beam line!)
@@ -419,7 +393,7 @@ std::unique_ptr<TrackCache> TrackStateProvider::createCacheEntry( TkCacheKey key
       if ( dz < -10 * Gaudi::Units::cm ) {
         auto z = track.firstState().z() + dz;
         if ( z > -100 * Gaudi::Units::cm ) { // beginning of velo
-          addState( *tc, z, LHCb::State::ClosestToBeam );
+          addState( tc, z, LHCb::State::Location::ClosestToBeam );
         }
       }
     }
@@ -429,9 +403,9 @@ std::unique_ptr<TrackCache> TrackStateProvider::createCacheEntry( TkCacheKey key
   // at the beamline and at rich2. For the trajectory approximation
   // used in DTF for Long-Long Ks, this is not enough. Add a state at
   // the end of the Velo.
-  if ( !track.checkFlag( LHCb::Track::Backward ) && track.hasVelo() &&
-       !track.stateAt( LHCb::State::FirstMeasurement ) ) {
-    addState( *tc, StateParameters::ZEndVelo, LHCb::State::EndVelo );
+  if ( !track.checkFlag( LHCb::Track::Flags::Backward ) && track.hasVelo() &&
+       !track.stateAt( LHCb::State::Location::FirstMeasurement ) ) {
+    addState( tc, StateParameters::ZEndVelo, LHCb::State::Location::EndVelo );
   }
 
   return tc;
@@ -441,13 +415,13 @@ std::unique_ptr<TrackCache> TrackStateProvider::createCacheEntry( TkCacheKey key
 // retrieve TrackCache entry for a given track (from the cache)
 //=============================================================================
 TrackCache& TrackStateProvider::cache( const LHCb::Track& track ) const {
-  auto key = trackID( track );
-  auto it  = m_trackcache.find( key );
-  if ( it == m_trackcache.end() ) {
-    auto ret = m_trackcache.emplace( key, createCacheEntry( key, track ) );
+  // get the cache from the stack
+  const auto key = trackID( track );
+  auto&      tc  = trackcache();
+  auto       it  = tc.find( key );
+  if ( it == tc.end() ) {
+    auto ret = tc.emplace( key, createCacheEntry( key, track ) );
     it       = ret.first;
   }
-  return *it->second;
+  return it->second;
 }
-
-const LHCb::TrackTraj* TrackStateProvider::trajectory( const LHCb::Track& track ) const { return &cache( track ); }
diff --git a/Tr/TrackFitter/src/TrackMasterFitter.cpp b/Tr/TrackFitter/src/TrackMasterFitter.cpp
index b439db15eadb23d6cf7808413504c01c602acce5..6c1b14d0e62974b2b296df4f314cccb92857fcd5 100644
--- a/Tr/TrackFitter/src/TrackMasterFitter.cpp
+++ b/Tr/TrackFitter/src/TrackMasterFitter.cpp
@@ -263,6 +263,9 @@ StatusCode TrackMasterFitter::fit_r( Track& track, std::any& accelCache, LHCb::P
   // any track that doesnt make it to the end is failed
   track.setFitStatus( Track::FitStatus::FitFailed );
 
+  // make sure to reset the stateprovider cache, no matter what happens next.
+  m_stateProvider->clearCache( track );
+
   // create the KalmanFitResult if it doesn't exist yet
   LHCb::KalmanFitResult* kalfitresult = dynamic_cast<LHCb::KalmanFitResult*>( track.fitResult() );
   if ( !kalfitresult ) {
diff --git a/Tr/TrackFitter/src/TrackMasterFitter.h b/Tr/TrackFitter/src/TrackMasterFitter.h
index 616cf30c6f6a82a941c7b92cbc3910e3808334c8..b77a3c316a6540f8eda397a2b94d77771dfdcf37 100644
--- a/Tr/TrackFitter/src/TrackMasterFitter.h
+++ b/Tr/TrackFitter/src/TrackMasterFitter.h
@@ -24,6 +24,7 @@
 #include "TrackInterfaces/ITrackFitter.h"
 #include "TrackInterfaces/ITrackKalmanFilter.h"
 #include "TrackInterfaces/ITrackProjectorSelector.h"
+#include "TrackInterfaces/ITrackStateProvider.h"
 
 // Forward declarations
 struct ITrackManipulator;
@@ -108,12 +109,13 @@ private:
   }
 
 private:
-  ToolHandle<ITrackExtrapolator>      m_extrapolator;     ///< extrapolator
-  ToolHandle<ITrackExtrapolator>      m_veloExtrapolator; ///< extrapolator for Velo-only tracks
-  ToolHandle<ITrackKalmanFilter>      m_trackNodeFitter;  ///< delegate to actual track fitter (which fits from nodes)
-  ToolHandle<IMeasurementProvider>    m_measProvider;
-  ToolHandle<IMaterialLocator>        m_materialLocator;
-  ToolHandle<ITrackProjectorSelector> m_projectorSelector;
+  ToolHandle<ITrackExtrapolator>        m_extrapolator;     ///< extrapolator
+  ToolHandle<ITrackExtrapolator>        m_veloExtrapolator; ///< extrapolator for Velo-only tracks
+  ToolHandle<ITrackKalmanFilter>        m_trackNodeFitter;  ///< delegate to actual track fitter (which fits from nodes)
+  ToolHandle<IMeasurementProvider>      m_measProvider;
+  ToolHandle<IMaterialLocator>          m_materialLocator;
+  ToolHandle<ITrackProjectorSelector>   m_projectorSelector;
+  PublicToolHandle<ITrackStateProvider> m_stateProvider{this, "StateProvider", "TrackStateProvider"};
 
 private:
   // job options
diff --git a/Tr/TrackInterfaces/TrackInterfaces/ITrackStateProvider.h b/Tr/TrackInterfaces/TrackInterfaces/ITrackStateProvider.h
index 752d2c526e4a50c7f59908850c4fe398ee11327c..2e9e3cbacafb6bff6c08c3c8e9d27248f6439da3 100644
--- a/Tr/TrackInterfaces/TrackInterfaces/ITrackStateProvider.h
+++ b/Tr/TrackInterfaces/TrackInterfaces/ITrackStateProvider.h
@@ -1,5 +1,5 @@
 /*****************************************************************************\
-* (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration      *
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
 *                                                                             *
 * This software is distributed under the terms of the GNU General Public      *
 * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
@@ -8,18 +8,17 @@
 * granted to it by virtue of its status as an Intergovernmental Organization  *
 * or submit itself to any jurisdiction.                                       *
 \*****************************************************************************/
-#ifndef TRACKINTERFACES_ITRACKSTATEPROVIDER_H
-#define TRACKINTERFACES_ITRACKSTATEPROVIDER_H 1
+#pragma once
 
 // Include files
 // -------------
 // from Gaudi
+#include "Event/Track.h"
 #include "Event/TrackParameters.h"
 #include "GaudiKernel/IAlgTool.h"
 
 // Forward declarations
 namespace LHCb {
-  class Track;
   class State;
   class TrackTraj;
 } // namespace LHCb
@@ -53,9 +52,8 @@ struct ITrackStateProvider : extend_interfaces<IAlgTool> {
   virtual const LHCb::TrackTraj* trajectory( const LHCb::Track& track ) const = 0;
 
   /// Clear the cache
-  virtual void clearCache() = 0;
+  virtual void clearCache() const = 0;
 
   /// Clear the cache for a particular track
-  virtual void clearCache( const LHCb::Track& track ) = 0;
+  virtual void clearCache( const LHCb::Track& track ) const = 0;
 };
-#endif // TRACKINTERFACES_ITRACKSTATEPROVIDER_H