diff --git a/include/opendht/dht_proxy_server.h b/include/opendht/dht_proxy_server.h
index 25cc8f205246348dff171806e07c534c032544f1..a864eaa383e3b8e4eaedefd97f3cc905810870a3 100644
--- a/include/opendht/dht_proxy_server.h
+++ b/include/opendht/dht_proxy_server.h
@@ -90,20 +90,19 @@ public:
         /** Average requests per second */
         double requestRate {0};
         /** Node Info **/
-        NodeInfo nodeInfo {};
+        std::shared_ptr<NodeInfo> nodeInfo {};
 
         std::string toString() const {
             std::ostringstream ss;
             ss << "Listens: " << listenCount << " Puts: " << putCount << " PushListeners: " << pushListenersCount << std::endl;
             ss << "Requests: " << requestRate << " per second." << std::endl;
-            auto& ni = nodeInfo;
-            auto& ipv4 = ni.ipv4;
-            if (ipv4.table_depth > 1) {
-                ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
-            }
-            auto& ipv6 = ni.ipv6;
-            if (ipv6.table_depth > 1) {
-                ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
+            if (nodeInfo) {
+                auto& ipv4 = nodeInfo->ipv4;
+                if (ipv4.table_depth > 1)
+                    ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
+                auto& ipv6 = nodeInfo->ipv6;
+                if (ipv6.table_depth > 1)
+                    ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
             }
             return ss.str();
         }
@@ -117,14 +116,15 @@ public:
             result["putCount"] = static_cast<Json::UInt64>(putCount);
             result["pushListenersCount"] = static_cast<Json::UInt64>(pushListenersCount);
             result["requestRate"] = requestRate;
-            result["nodeInfo"] = nodeInfo.toJson();
+            if (nodeInfo)
+                result["nodeInfo"] = nodeInfo->toJson();
             return result;
         }
     };
 
-    ServerStats stats() const { return stats_; }
+    std::shared_ptr<ServerStats> stats() const { return stats_; }
 
-    void updateStats() const;
+    std::shared_ptr<ServerStats> updateStats(std::shared_ptr<NodeInfo> info) const;
 
     std::shared_ptr<DhtRunner> getNode() const { return dht_; }
 
@@ -327,9 +327,8 @@ private:
 
     std::shared_ptr<dht::Logger> logger_;
 
-    mutable std::mutex statsMutex_;
-    mutable ServerStats stats_;
-    mutable NodeInfo nodeInfo_ {};
+    mutable std::shared_ptr<ServerStats> stats_;
+    mutable std::shared_ptr<NodeInfo> nodeInfo_ {};
     std::unique_ptr<asio::steady_timer> printStatsTimer_;
 
     // Thread-safe access to listeners map.
diff --git a/src/dht_proxy_server.cpp b/src/dht_proxy_server.cpp
index 7a41d45b59365d18ad1630752cfcec4cefc81c23..25b5959167b44379ddab924ccc968a3087a0ee3e 100644
--- a/src/dht_proxy_server.cpp
+++ b/src/dht_proxy_server.cpp
@@ -36,6 +36,7 @@
 #include <iostream>
 
 using namespace std::placeholders;
+using namespace std::chrono_literals;
 
 #ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
 namespace restinio {
@@ -263,7 +264,7 @@ DhtProxyServer::DhtProxyServer(
     }
     dht->forwardAllMessages(true);
 
-    printStatsTimer_ = std::make_unique<asio::steady_timer>(io_context(), PRINT_STATS_PERIOD);
+    printStatsTimer_ = std::make_unique<asio::steady_timer>(io_context(), 0s);
     printStatsTimer_->async_wait(std::bind(&DhtProxyServer::handlePrintStats, this, std::placeholders::_1));
 }
 
@@ -344,20 +345,23 @@ DhtProxyServer::addServerSettings(ServerSettings& settings, const unsigned int m
     settings.connection_state_listener(connListener_);
 }
 
-void
-DhtProxyServer::updateStats() const
+std::shared_ptr<DhtProxyServer::ServerStats>
+DhtProxyServer::updateStats(std::shared_ptr<NodeInfo> info) const
 {
     auto now = clock::now();
     auto last = lastStatsReset_.exchange(now);
     auto count = requestNum_.exchange(0);
     auto dt = std::chrono::duration<double>(now - last);
-    stats_.requestRate = count / dt.count();
+    auto sstats = std::make_shared<ServerStats>();
+    auto& stats = *sstats;
+    stats.requestRate = count / dt.count();
 #ifdef OPENDHT_PUSH_NOTIFICATIONS
-    stats_.pushListenersCount = pushListeners_.size();
+    stats.pushListenersCount = pushListeners_.size();
 #endif
-    stats_.putCount = puts_.size();
-    stats_.listenCount = listeners_.size();
-    stats_.nodeInfo = nodeInfo_;
+    stats.putCount = puts_.size();
+    stats.listenCount = listeners_.size();
+    stats.nodeInfo = info;
+    return sstats;
 }
 
 void
@@ -372,13 +376,12 @@ DhtProxyServer::handlePrintStats(const asio::error_code &ec)
     if (io_context().stopped())
         return;
 
-    if (dht_){
-        updateStats();
+    if (auto dht = dht_) {
         // Refresh stats cache
-        auto newInfo = dht_->getNodeInfo();
-        std::lock_guard<std::mutex> lck(statsMutex_);
-        nodeInfo_ = std::move(newInfo);
-        auto json = nodeInfo_.toJson();
+        auto newInfo = std::make_shared<NodeInfo>(dht->getNodeInfo());
+        stats_ = updateStats(newInfo);
+        nodeInfo_ = newInfo;
+        auto json = newInfo->toJson();
         auto str = Json::writeString(jsonBuilder_, json);
         if (logger_)
             logger_->d("[proxy:server] [stats] %s", str.c_str());
@@ -477,12 +480,12 @@ DhtProxyServer::getNodeInfo(restinio::request_handle_t request,
                             restinio::router::route_params_t /*params*/) const
 {
     Json::Value result;
-    std::lock_guard<std::mutex> lck(statsMutex_);
-    if (nodeInfo_.ipv4.good_nodes == 0 &&
-        nodeInfo_.ipv6.good_nodes == 0){
-        nodeInfo_ = dht_->getNodeInfo();
+    auto nodeInfo = nodeInfo_;
+    if (not nodeInfo) {
+        nodeInfo = std::make_shared<NodeInfo>(dht_->getNodeInfo());
+        nodeInfo_ = nodeInfo;
     }
-    result = nodeInfo_.toJson();
+    result = nodeInfo->toJson();
     // [ipv6:ipv4]:port or ipv4:port
     result["public_ip"] = request->remote_endpoint().address().to_string();
     auto output = Json::writeString(jsonBuilder_, result) + "\n";
@@ -498,8 +501,8 @@ DhtProxyServer::getStats(restinio::request_handle_t request,
 {
     requestNum_++;
     try {
-        if (dht_){
-            auto output = Json::writeString(jsonBuilder_, stats_.toJson()) + "\n";
+        if (auto stats = stats_) {
+            auto output = Json::writeString(jsonBuilder_, stats->toJson()) + "\n";
             auto response = initHttpResponse(request->create_response());
             response.append_body(output);
             response.done();
diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp
index bb4cee6a5b7a4f146f660fff2b6aff91c9ccef8a..76632b9cfa78c613b31d01626effdfea4cea762a 100644
--- a/tools/dhtnode.cpp
+++ b/tools/dhtnode.cpp
@@ -152,8 +152,11 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
             std::cout << nodeInfo.ipv6.toString() << std::endl;
 #ifdef OPENDHT_PROXY_SERVER
             for (const auto& proxy : proxies) {
-                std::cout << "Stats for proxy on port " << proxy.first << std::endl;
-                std::cout << "  " << proxy.second->stats().toString() << std::endl;
+                std::cout << "Stats for proxy server on port " << proxy.first << std::endl;
+                if (auto stats = proxy.second->stats())
+                    std::cout << "  " << stats->toString() << std::endl;
+                else
+                    std::cout << "  (stats not available yet)" << std::endl;                
             }
 #endif
             continue;