diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index 55efd285c33d17a7881e9b591572f2c3b28ac03c..af1a9948551683b812ab490766a58bca8ddecb5f 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -62,6 +62,7 @@ set(GaudiExamples_srcs
     src/PluginService/*.cpp
     src/ToolHandles/*.cpp
     src/ReEntAlg/*.cpp
+    src/ConditionAccessor/*.cpp
 )
 
 # Add the sources requiring non-standard externals:
@@ -113,7 +114,7 @@ endif()
 # Now set up the libraries:
 gaudi_add_library( GaudiExamplesLib src/Lib/*.cpp
    LINK_LIBRARIES GaudiKernel
-   PUBLIC_HEADERS GaudiExamples )
+   PUBLIC_HEADERS GaudiExamples Gaudi)
 
 gaudi_add_module( GaudiExamples ${GaudiExamples_srcs}
    INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${extra_includes}
diff --git a/GaudiExamples/Gaudi/Examples/Conditions/ConditionAccessorHolder.h b/GaudiExamples/Gaudi/Examples/Conditions/ConditionAccessorHolder.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3adb9e9af846fb98883fbad8c9a5b136a3c3d0a
--- /dev/null
+++ b/GaudiExamples/Gaudi/Examples/Conditions/ConditionAccessorHolder.h
@@ -0,0 +1,155 @@
+#pragma once
+
+#include <GaudiKernel/EventContext.h>
+#include <GaudiKernel/Property.h>
+#include <GaudiKernel/StateMachine.h>
+#include <GaudiKernel/StatusCode.h>
+#include <any>
+#include <mutex>
+#include <string>
+
+namespace Gaudi::Examples::Conditions {
+  namespace details {
+    /// Example class to implement an actual backend for Gaudi::Examples::Conditions::ConditionAccessorHolder
+    class ConditionsStore {
+    public:
+      using ConditionContext = int;
+      using ConditionKey     = std::string;
+
+      static ConditionsStore& instance();
+
+      void declareKey( const ConditionKey& key );
+
+      const ConditionContext& getConditionContext( const EventContext& ctx ) const;
+
+      template <typename T>
+      const T& getCondition( const ConditionKey& key, const ConditionContext& ctx ) const {
+        return *std::any_cast<T>( getConditionAny( key, ctx ) );
+      }
+
+    private:
+      ConditionsStore() = default;
+      const std::any* getConditionAny( const ConditionKey& key, const ConditionContext& ctx ) const;
+
+      using IOVSlot  = std::map<ConditionKey, std::any>;
+      using IOVSlots = std::map<ConditionContext, IOVSlot>;
+
+      mutable std::mutex     m_storageMtx;
+      mutable IOVSlots       m_storage;
+      std::set<ConditionKey> m_requestedKeys;
+    };
+  } // namespace details
+
+  /// Example of a ConditionAccessorHolder implementation.
+  ///
+  /// Requirements are:
+  /// - inherit from the template argument (forwarding the constructor)
+  /// - provide the following types (could be type aliases):
+  ///   - `base_class` (this type)
+  ///   - `ConditionAccessor<T>`
+  ///   - `ConditionContext`
+  ///   - `ConditionKey`
+  /// - provide the method
+  ///   - `const ConditionContext& getConditionContext( const EventContext& ) const`
+  /// - provide a method to handle registration of ConditionAccessor instances for
+  ///   internal bookkeeping (here represented by `void registerConditionAccessor<T>( ConditionAccessor<T>& accessor )`)
+  ///
+  /// Component classes that require conditions have to inherit from this class,
+  /// templated with the component base class. E.g.
+  /// \code
+  /// class MyConditionAlgorithm final : ConditionAccessorHolder<Gaudi::Algorithm> {
+  ///   // ...
+  /// };
+  /// \endcode
+  ///
+  /// See Gaudi::Examples::Conditions::UserAlg for example.
+  template <typename Base>
+  class ConditionAccessorHolder : public Base {
+  public:
+    /// Forward to base class constructor
+    using Base::Base;
+
+    /// Helper to expose this class to specializations without having to spell
+    /// the whole name (see Gaudi::Examples::Conditions::UserAlg)
+    using base_class = ConditionAccessorHolder<Base>;
+
+    /// Forward backend specific ConditionContext to specializations.
+    ///
+    /// It is used to refer to a specific conditions slot.
+    using ConditionContext = details::ConditionsStore::ConditionContext;
+
+    /// Forward backend specific ConditionKey to specializations.
+    ///
+    /// Used to identify a specific condition in a condition slot.
+    using ConditionKey = details::ConditionsStore::ConditionKey;
+
+    /// Class wrapping the communication between condition users and conditions backend.
+    ///
+    /// Users must use instances of this class as data members, passing `this` to the
+    /// data member constructor.
+    ///
+    /// See Gaudi::Examples::Conditions::UserAlg::m_cond
+    template <typename T>
+    class ConditionAccessor {
+    public:
+      /// Constructor a ConditionAccessor instance registering it to the current holder.
+      ConditionAccessor( base_class* owner, const std::string& keyName, const ConditionKey& keyDefault,
+                         const std::string& keyDoc = "" )
+          : m_key{owner, keyName, keyDefault, keyDoc} {
+        owner->registerConditionAccessor( *this );
+      }
+
+      /// Helper to access the key of the current accessor.
+      ///
+      /// @note can only be modified via the associated property
+      const ConditionKey& key() const { return m_key; }
+
+      /// Get the condition value for the requested condition slot.
+      const T& get( const ConditionContext& ctx ) const {
+        return details::ConditionsStore::instance().getCondition<T>( key(), ctx );
+      }
+
+    private:
+      /// Internal property object for the condition key.
+      Gaudi::Property<ConditionKey> m_key;
+    };
+
+    StatusCode initialize() override {
+      auto sc = Base::initialize();
+      if ( !sc ) return sc;
+
+      // backend-specific initialization
+
+      // trigger delayed registrations
+      for ( auto& action : m_delayedRegistrations ) { action(); }
+      m_delayedRegistrations.clear();
+
+      return sc;
+    }
+
+    /// Helper to map the event being processed to the corresponding conditions slot.
+    const ConditionContext& getConditionContext( const EventContext& ctx ) const {
+      return details::ConditionsStore::instance().getConditionContext( ctx );
+    }
+
+  private:
+    template <typename T>
+    friend class ConditionAccessor;
+
+    /// Register a ConditionAccessor instance to internal bookkeeping.
+    template <typename T>
+    void registerConditionAccessor( ConditionAccessor<T>& accessor ) {
+      if ( this->targetFSMState() == Gaudi::StateMachine::INITIALIZED ) {
+        details::ConditionsStore::instance().declareKey( accessor.key() );
+      } else {
+        m_delayedRegistrations.push_back( [this, &accessor]() { registerConditionAccessor( accessor ); } );
+      }
+    }
+
+    /// Helper to postpone the registration to the backend.
+    ///
+    /// In Gaudi properties are set during initialize, so, in this example implementation,
+    /// the registration has to be delayed from construction time to initialization time.
+    std::list<std::function<void()>> m_delayedRegistrations;
+  };
+} // namespace Gaudi::Examples::Conditions
diff --git a/GaudiExamples/src/ConditionAccessor/Backend.cpp b/GaudiExamples/src/ConditionAccessor/Backend.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2a07f6220b6312044506f2bfa3a053a0b6598eb1
--- /dev/null
+++ b/GaudiExamples/src/ConditionAccessor/Backend.cpp
@@ -0,0 +1,37 @@
+#include <Gaudi/Examples/Conditions/ConditionAccessorHolder.h>
+#include <GaudiKernel/System.h>
+
+namespace Gaudi::Examples::Conditions::details {
+  ConditionsStore& ConditionsStore::instance() {
+    static ConditionsStore store{};
+    return store;
+  }
+
+  void ConditionsStore::declareKey( const ConditionKey& key ) {
+    if ( std::get<1>( m_requestedKeys.emplace( key ) ) ) {
+      std::cout << "ConditionsStore: requested condition " << key << '\n';
+    }
+  }
+
+  const ConditionsStore::ConditionContext& ConditionsStore::getConditionContext( const EventContext& ctx ) const {
+    static ConditionContext current_iov = 0;
+
+    current_iov = ctx.evt() % 2;
+    return current_iov;
+  }
+
+  const std::any* ConditionsStore::getConditionAny( const ConditionKey& key, const ConditionContext& ctx ) const {
+    std::lock_guard<std::mutex> lg{m_storageMtx};
+    if ( m_storage.find( ctx ) == end( m_storage ) ) {
+      std::cout << "ConditionsStore: first access to store " << ctx << '\n';
+      auto& store = m_storage[ctx];
+      for ( const auto& key : m_requestedKeys ) {
+        std::cout << "ConditionsStore: prepare condition " << key << '\n';
+        store.emplace( key, ctx );
+      }
+    } else {
+      std::cout << "ConditionsStore: using existing store " << ctx << '\n';
+    }
+    return &m_storage[ctx][key];
+  }
+} // namespace Gaudi::Examples::Conditions::details
diff --git a/GaudiExamples/src/ConditionAccessor/User.cpp b/GaudiExamples/src/ConditionAccessor/User.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab681fcb7060b9302eb4cd88ad89a49ed2a16c96
--- /dev/null
+++ b/GaudiExamples/src/ConditionAccessor/User.cpp
@@ -0,0 +1,41 @@
+#include <Gaudi/Algorithm.h>
+#include <Gaudi/Examples/Conditions/ConditionAccessorHolder.h>
+
+namespace Gaudi::Examples::Conditions {
+  /// Example of a simple algorithm using conditions via the ConditionAccessorHolder
+  /// pattern.
+  class UserAlg : public ConditionAccessorHolder<Algorithm> {
+    /// Delegate to base class constructor.
+    using base_class::base_class;
+
+    /// Data member to access condition values for the current event.
+    ConditionAccessor<int> m_cond{this, "MyCondition", "condition/key"};
+
+    StatusCode initialize() override {
+      auto status = base_class::initialize();
+      if ( !status ) return status;
+
+      info() << "initialize" << endmsg;
+
+      return status;
+    }
+
+    StatusCode execute( const EventContext& ctx ) const override {
+      // get the condition slot for the current event
+      const auto& condCtx = getConditionContext( ctx );
+      // get the condition value from the current condition slot.
+      const auto& cond = m_cond.get( condCtx );
+
+      info() << "got condition value " << cond << endmsg;
+
+      return StatusCode::SUCCESS;
+    }
+
+    StatusCode finalize() override {
+      info() << "finalize" << endmsg;
+
+      return base_class::finalize();
+    }
+  };
+  DECLARE_COMPONENT( UserAlg )
+} // namespace Gaudi::Examples::Conditions
diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/conditions.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/conditions.qmt
new file mode 100644
index 0000000000000000000000000000000000000000..a28dfd9a52d5abcdcfe4c204cf5672e5aa834391
--- /dev/null
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/conditions.qmt
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="options"><text>
+from Gaudi.Configuration import *
+from Configurables import Gaudi__Examples__Conditions__UserAlg as UA
+
+ApplicationMgr(EvtSel="NONE",
+               EvtMax=5,
+               TopAlg=[
+                   UA("ConditionsUser1"),
+                   UA("ConditionsUser2", MyCondition="another/key")])
+</text></argument>
+<argument name="reference"><text>refs/ConditionsAccess.ref</text></argument>
+</extension>
diff --git a/GaudiExamples/tests/qmtest/refs/ConditionsAccess.ref b/GaudiExamples/tests/qmtest/refs/ConditionsAccess.ref
new file mode 100644
index 0000000000000000000000000000000000000000..5a117b3ca37abf7a2c3c67bf9519bcc755fcf936
--- /dev/null
+++ b/GaudiExamples/tests/qmtest/refs/ConditionsAccess.ref
@@ -0,0 +1,46 @@
+# setting LC_ALL to "C"
+ApplicationMgr    SUCCESS 
+====================================================================================================================================
+                                                   Welcome to ApplicationMgr (GaudiCoreSvc v30r5)
+                                          running on marco-XPS-13 on Fri Feb  1 12:41:18 2019
+====================================================================================================================================
+ApplicationMgr       INFO Application Manager Configured successfully
+ConditionsStore: requested condition condition/key
+ConditionsUser1      INFO initialize
+ConditionsStore: requested condition another/key
+ConditionsUser2      INFO initialize
+EventLoopMgr      WARNING Unable to locate service "EventSelector" 
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...WARNING Histograms saving not required.
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr       INFO Application Manager Started successfully
+ConditionsStore: first access to store 0
+ConditionsStore: prepare condition another/key
+ConditionsStore: prepare condition condition/key
+ConditionsUser1      INFO got condition value 0
+ConditionsStore: using existing store 0
+ConditionsUser2      INFO got condition value 0
+ConditionsStore: first access to store 1
+ConditionsStore: prepare condition another/key
+ConditionsStore: prepare condition condition/key
+ConditionsUser1      INFO got condition value 1
+ConditionsStore: using existing store 1
+ConditionsUser2      INFO got condition value 1
+ConditionsStore: using existing store 0
+ConditionsUser1      INFO got condition value 0
+ConditionsStore: using existing store 0
+ConditionsUser2      INFO got condition value 0
+ConditionsStore: using existing store 1
+ConditionsUser1      INFO got condition value 1
+ConditionsStore: using existing store 1
+ConditionsUser2      INFO got condition value 1
+ConditionsStore: using existing store 0
+ConditionsUser1      INFO got condition value 0
+ConditionsStore: using existing store 0
+ConditionsUser2      INFO got condition value 0
+ApplicationMgr       INFO Application Manager Stopped successfully
+ConditionsUser1      INFO finalize
+ConditionsUser2      INFO finalize
+EventLoopMgr         INFO Histograms converted successfully according to request.
+ApplicationMgr       INFO Application Manager Finalized successfully
+ApplicationMgr       INFO Application Manager Terminated successfully