diff --git a/include/opendht/callbacks.h b/include/opendht/callbacks.h
index cea81f1a67a526b04b801a3a991e11352965a291..3a4007257a76908f2a6c1064420945f583b68f2f 100644
--- a/include/opendht/callbacks.h
+++ b/include/opendht/callbacks.h
@@ -46,7 +46,7 @@ struct OPENDHT_PUBLIC Config {
     /** DHT node ID */
     InfoHash node_id;
 
-    /** 
+    /**
      * DHT network ID. A node will only talk with other nodes having
      * the same network ID.
      * Network ID 0 (default) represents the main public network.
diff --git a/include/opendht/dhtrunner.h b/include/opendht/dhtrunner.h
index c7c20dc241b0a8d886232093a454c61342ee29e1..1a7eecfe2d9b6a02e95ffde6b8a15a1d73fc941d 100644
--- a/include/opendht/dhtrunner.h
+++ b/include/opendht/dhtrunner.h
@@ -283,7 +283,7 @@ public:
     std::string getStorageLog(const InfoHash&) const;
     std::string getRoutingTablesLog(sa_family_t af) const;
     std::string getSearchesLog(sa_family_t af = AF_UNSPEC) const;
-    std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;    
+    std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;
     std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC);
     std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC);
 
@@ -370,7 +370,7 @@ private:
      * nodes so that the DHT node can recover quickly from losing connection
      * with the network.
      */
-    void tryBootstrapCoutinuously();
+    void tryBootstrapContinuously();
 
     void doRun(const sockaddr_in* sin4, const sockaddr_in6* sin6, SecureDhtConfig config);
     time_point loop_();
diff --git a/src/dht.cpp b/src/dht.cpp
index 28af1858dcdfcbb347ca245e24221b230d112587..5c59a716b1c7fb1eb7ceb8d0610e05b5aa1ca1d9 100644
--- a/src/dht.cpp
+++ b/src/dht.cpp
@@ -2829,11 +2829,12 @@ Dht::bucketMaintenance(RoutingTable& list)
     std::bernoulli_distribution rand_trial(1./8.);
     std::bernoulli_distribution rand_trial_38(1./38.);
 
+    bool sent {false};
     for (auto b = list.begin(); b != list.end(); ++b) {
         if (b->time < scheduler.time() - std::chrono::minutes(10) || b->nodes.empty()) {
             /* This bucket hasn't seen any positive confirmation for a long
-               time.  Pick a random id in this bucket's range, and send
-               a request to a random node. */
+               time. Pick a random id in this bucket's range, and send a request
+               to a random node. */
             InfoHash id = list.randomId(b);
             auto q = b;
             /* If the bucket is empty, we try to fill it from a neighbour.
@@ -2848,7 +2849,7 @@ Dht::bucketMaintenance(RoutingTable& list)
             }
 
             auto n = q->randomNode();
-            if (n) {
+            if (n and not n->isPendingMessage()) {
                 want_t want = -1;
 
                 if (network_engine.want() != want) {
@@ -2872,16 +2873,14 @@ Dht::bucketMaintenance(RoutingTable& list)
                         const auto& end = scheduler.time();
                         using namespace std::chrono;
                         DHT_LOG.d(n->id, "[node %s] bucket maintenance op expired after %llu ms", n->toString().c_str(), duration_cast<milliseconds>(end-start).count());
-                        scheduler.edit(nextNodesConfirmation, end + 3 * Node::NODE_EXPIRE_TIME);
+                        scheduler.edit(nextNodesConfirmation, end + Node::MAX_RESPONSE_TIME);
                     }
                 });
-                /* In order to avoid sending queries back-to-back,
-                   give up for now and reschedule us soon. */
-                return true;
+                sent = true;
             }
         }
     }
-    return false;
+    return sent;
 }
 
 void
diff --git a/src/dhtrunner.cpp b/src/dhtrunner.cpp
index 395578393021eef704973f4d6af548141cdc8302..bd8a5b23a3c616c6164370cfaf5dc6797a1dac33 100644
--- a/src/dhtrunner.cpp
+++ b/src/dhtrunner.cpp
@@ -348,7 +348,7 @@ DhtRunner::loop_()
             // We have lost connection with the DHT.  Try to recover using bootstrap nodes.
             std::unique_lock<std::mutex> lck(bootstrap_mtx);
             bootstrap_nodes = bootstrap_nodes_all;
-            tryBootstrapCoutinuously();
+            tryBootstrapContinuously();
         } else {
             std::unique_lock<std::mutex> lck(bootstrap_mtx);
             bootstrap_nodes.clear();
@@ -618,7 +618,7 @@ DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, Done
 }
 
 void
-DhtRunner::tryBootstrapCoutinuously()
+DhtRunner::tryBootstrapContinuously()
 {
     if (bootstrap_thread.joinable()) {
         if (bootstraping)
@@ -707,7 +707,7 @@ DhtRunner::bootstrap(const std::string& host, const std::string& service)
     std::lock_guard<std::mutex> lck(bootstrap_mtx);
     bootstrap_nodes_all.emplace_back(host, service);
     bootstrap_nodes.emplace_back(host, service);
-    tryBootstrapCoutinuously();
+    tryBootstrapContinuously();
 }
 
 void
diff --git a/src/routing_table.cpp b/src/routing_table.cpp
index cb6abe2c390f0739ac0a50162b1795c90f1a5e66..576b3d14cfe4aa9df11190455ac169e1d593ffee 100644
--- a/src/routing_table.cpp
+++ b/src/routing_table.cpp
@@ -17,10 +17,21 @@ Bucket::randomNode()
 {
     if (nodes.empty())
         return nullptr;
-    std::uniform_int_distribution<unsigned> rand_node(0, nodes.size()-1);
+    unsigned expired_node_count = std::count_if(nodes.cbegin(), nodes.cend(), [](const decltype(nodes)::value_type& node) {
+        return node->isExpired();
+    });
+    auto prioritize_not_expired = expired_node_count < nodes.size();
+
+    std::uniform_int_distribution<unsigned> rand_node(0, prioritize_not_expired
+            ? nodes.size() - expired_node_count - 1
+            : nodes.size()-1);
     unsigned nn = rand_node(rd);
-    for (auto& n : nodes)
-        if (not nn--) return n;
+    for (auto& n : nodes) {
+        if (not (prioritize_not_expired and n->isExpired())) {
+            if (not nn--)
+                return n;
+        }
+    }
     return nodes.back();
 }