diff --git a/include/opendht/node_cache.h b/include/opendht/node_cache.h
index a00685a619a68f59424843e356a1398107a411b6..c7906938d1eea252b81792a3f2f20127e51c7734 100644
--- a/include/opendht/node_cache.h
+++ b/include/opendht/node_cache.h
@@ -38,21 +38,15 @@ struct NodeCache {
     void clearBadNodes(sa_family_t family = 0);
 
 private:
-    struct NodeTree {
-        std::shared_ptr<Node> get(const InfoHash& id);
-        std::shared_ptr<Node> get(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed);
-
+    class NodeMap : public std::map<InfoHash, std::weak_ptr<Node>> {
+    public:
+        std::shared_ptr<Node> getNode(const InfoHash& id);
+        std::shared_ptr<Node> getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed);
         void clearBadNodes();
-
-    private:
-        std::shared_ptr<Node> getLocal(const InfoHash& id);
-
-        std::vector<NodeTree> childs;
-        std::vector<std::weak_ptr<Node>> nodes;
     };
 
-    NodeTree cache_4;
-    NodeTree cache_6;
+    NodeMap cache_4;
+    NodeMap cache_6;
 };
 
 }
diff --git a/src/node_cache.cpp b/src/node_cache.cpp
index a579f416b39511a4e71a09fa8a61413226456a4e..34aeb18f063c222518d0a7ae12918573cde0a4d2 100644
--- a/src/node_cache.cpp
+++ b/src/node_cache.cpp
@@ -23,12 +23,12 @@ namespace dht {
 
 std::shared_ptr<Node>
 NodeCache::getNode(const InfoHash& id, sa_family_t family) {
-    return (family == AF_INET ? cache_4 : cache_6).get(id);
+    return (family == AF_INET ? cache_4 : cache_6).getNode(id);
 }
 
 std::shared_ptr<Node>
 NodeCache::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm) {
-    return (sa->sa_family == AF_INET ? cache_4 : cache_6).get(id, sa, sa_len, now, confirm);
+    return (sa->sa_family == AF_INET ? cache_4 : cache_6).getNode(id, sa, sa_len, now, confirm);
 }
 
 void
@@ -43,82 +43,40 @@ NodeCache::clearBadNodes(sa_family_t family)
 }
 
 std::shared_ptr<Node>
-NodeCache::NodeTree::getLocal(const InfoHash& id)
+NodeCache::NodeMap::getNode(const InfoHash& id)
 {
-    for (auto it = nodes.begin(); it != nodes.end();) {
-        if (auto n = it->lock()) {
-            if (n->id == id) return n;
-            ++it;
-        } else {
-            it = nodes.erase(it);
-        }
-    }
+    auto wn = find(id);
+    if (wn == end())
+        return {};
+    if (auto n = wn->second.lock())
+        return n;
+    erase(wn);
     return {};
 }
 
 std::shared_ptr<Node>
-NodeCache::NodeTree::get(const InfoHash& id)
+NodeCache::NodeMap::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm)
 {
-    NodeTree* t = this;
-    for (auto b : id) {
-        if (t->childs.empty())
-            return t->getLocal(id);
-        else
-            t = &t->childs[b];
-    }
-    return {};
-}
-
-std::shared_ptr<Node>
-NodeCache::NodeTree::get(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm)
-{
-    // find the bucket
-    NodeTree* t = this;
-    size_t offset = 0;
-    while (not t->childs.empty() and offset < 4)
-        t = &t->childs[id[offset++]];
-
-    // find node in bucket
-    auto node = t->getLocal(id);
+    auto it = emplace(id, std::weak_ptr<Node>{});
+    auto node = it.first->second.lock();
     if (not node) {
         node = std::make_shared<Node>(id, sa, sa_len);
-
-        // insert node in bucket
-        if (t->nodes.size() >= 8 && offset < 4) {
-            offset++;
-            t->childs.resize(256);
-            for (auto& w : t->nodes) {
-                if (auto tn = w.lock()) {
-                    t->childs[tn->id[offset]].nodes.emplace_back(std::move(w));
-                }
-            }
-            t->nodes = {};
-            t->childs[id[offset]].nodes.emplace_back(node);
-        } else {
-            t->nodes.emplace_back(node);
-        }
+        it.first->second = node;
     } else if (confirm || node->time < now - Node::NODE_EXPIRE_TIME) {
         node->update(sa, sa_len);
     }
-    /*if (confirm)
-        node->received(now, confirm >= 2);*/
     return node;
 }
 
 void
-NodeCache::NodeTree::clearBadNodes() {
-    if (childs.empty()) {
-        for (auto it = nodes.begin(); it != nodes.end();) {
-            if (auto n = it->lock()) {
-                n->reset();
-                ++it;
-            } else {
-                it = nodes.erase(it);
-            }
+NodeCache::NodeMap::clearBadNodes() {
+    for (auto it = cbegin(); it != cend();) {
+        if (auto n = it->second.lock()) {
+            n->reset();
+            ++it;
+        } else {
+            erase(it++);
         }
-    } else {
-        for (auto& c : childs)
-            c.clearBadNodes();
     }
 }