diff --git a/protocols/kad/src/jobs.rs b/protocols/kad/src/jobs.rs
index af07076018e..e65dcd40e42 100644
--- a/protocols/kad/src/jobs.rs
+++ b/protocols/kad/src/jobs.rs
@@ -87,6 +87,7 @@ struct PeriodicJob<T> {
 }
 
 impl<T> PeriodicJob<T> {
+    #[cfg(test)]
     fn is_running(&self) -> bool {
         match self.state {
             PeriodicJobState::Running(..) => true,
@@ -96,6 +97,7 @@ impl<T> PeriodicJob<T> {
 
     /// Cuts short the remaining delay, if the job is currently waiting
     /// for the delay to expire.
+    #[cfg(test)]
     fn asap(&mut self) {
         if let PeriodicJobState::Waiting(delay, deadline) = &mut self.state {
             let new_deadline = Instant::now().checked_sub(Duration::from_secs(1)).unwrap();
@@ -169,6 +171,7 @@ impl PutRecordJob {
     }
 
     /// Checks whether the job is currently running.
+    #[cfg(test)]
     pub(crate) fn is_running(&self) -> bool {
         self.inner.is_running()
     }
@@ -177,6 +180,7 @@ impl PutRecordJob {
     /// for the delay to expire.
     ///
     /// The job is guaranteed to run on the next invocation of `poll`.
+    #[cfg(test)]
     pub(crate) fn asap(&mut self, publish: bool) {
         if publish {
             self.next_publish = Some(Instant::now().checked_sub(Duration::from_secs(1)).unwrap())
@@ -273,6 +277,7 @@ impl AddProviderJob {
     }
 
     /// Checks whether the job is currently running.
+    #[cfg(test)]
     pub(crate) fn is_running(&self) -> bool {
         self.inner.is_running()
     }
@@ -281,6 +286,7 @@ impl AddProviderJob {
     /// for the delay to expire.
     ///
     /// The job is guaranteed to run on the next invocation of `poll`.
+    #[cfg(test)]
     pub(crate) fn asap(&mut self) {
         self.inner.asap()
     }
diff --git a/protocols/kad/src/kbucket/bucket.rs b/protocols/kad/src/kbucket/bucket.rs
index bd0c5903a4a..d70161919e1 100644
--- a/protocols/kad/src/kbucket/bucket.rs
+++ b/protocols/kad/src/kbucket/bucket.rs
@@ -54,10 +54,6 @@ pub enum NodeStatus {
 }
 
 impl<TKey, TVal> PendingNode<TKey, TVal> {
-    pub(crate) fn key(&self) -> &TKey {
-        &self.node.key
-    }
-
     pub(crate) fn status(&self) -> NodeStatus {
         self.status
     }
@@ -70,6 +66,7 @@ impl<TKey, TVal> PendingNode<TKey, TVal> {
         Instant::now() >= self.replace
     }
 
+    #[cfg(test)]
     pub(crate) fn set_ready_at(&mut self, t: Instant) {
         self.replace = t;
     }
@@ -191,11 +188,6 @@ where
             .filter(|p| p.node.key.as_ref() == key.as_ref())
     }
 
-    /// Returns a reference to a node in the bucket.
-    pub(crate) fn get(&self, key: &TKey) -> Option<&Node<TKey, TVal>> {
-        self.position(key).map(|p| &self.nodes[p.0])
-    }
-
     /// Returns an iterator over the nodes in the bucket, together with their status.
     pub(crate) fn iter(&self) -> impl Iterator<Item = (&Node<TKey, TVal>, NodeStatus)> {
         self.nodes
@@ -398,22 +390,19 @@ where
         }
     }
 
-    /// Checks whether the given position refers to a connected node.
-    pub(crate) fn is_connected(&self, pos: Position) -> bool {
-        self.status(pos) == NodeStatus::Connected
-    }
-
     /// Gets the number of entries currently in the bucket.
     pub(crate) fn num_entries(&self) -> usize {
         self.nodes.len()
     }
 
     /// Gets the number of entries in the bucket that are considered connected.
+    #[cfg(test)]
     pub(crate) fn num_connected(&self) -> usize {
         self.first_connected_pos.map_or(0, |i| self.nodes.len() - i)
     }
 
     /// Gets the number of entries in the bucket that are considered disconnected.
+    #[cfg(test)]
     pub(crate) fn num_disconnected(&self) -> usize {
         self.nodes.len() - self.num_connected()
     }
diff --git a/protocols/kad/src/kbucket/entry.rs b/protocols/kad/src/kbucket/entry.rs
index 0794ace4202..c38aac4a483 100644
--- a/protocols/kad/src/kbucket/entry.rs
+++ b/protocols/kad/src/kbucket/entry.rs
@@ -135,20 +135,6 @@ where
         }
     }
 
-    /// Returns the key of the entry.
-    ///
-    /// Returns `None` if the `Key` used to construct this `Entry` is not a valid
-    /// key for an entry in a bucket, which is the case for the `local_key` of
-    /// the `KBucketsTable` referring to the local node.
-    pub(crate) fn key(&self) -> Option<&TKey> {
-        match self {
-            Entry::Present(entry, _) => Some(entry.key()),
-            Entry::Pending(entry, _) => Some(entry.key()),
-            Entry::Absent(entry) => Some(entry.key()),
-            Entry::SelfEntry => None,
-        }
-    }
-
     /// Returns the value associated with the entry.
     ///
     /// Returns `None` if the entry is absent from any bucket or refers to the
@@ -175,11 +161,6 @@ where
         PresentEntry(EntryRef { bucket, key })
     }
 
-    /// Returns the key of the entry.
-    pub(crate) fn key(&self) -> &TKey {
-        self.0.key
-    }
-
     /// Returns the value associated with the key.
     pub(crate) fn value(&mut self) -> &mut TVal {
         &mut self
@@ -218,11 +199,6 @@ where
         PendingEntry(EntryRef { bucket, key })
     }
 
-    /// Returns the key of the entry.
-    pub(crate) fn key(&self) -> &TKey {
-        self.0.key
-    }
-
     /// Returns the value associated with the key.
     pub(crate) fn value(&mut self) -> &mut TVal {
         self.0
@@ -262,11 +238,6 @@ where
         AbsentEntry(EntryRef { bucket, key })
     }
 
-    /// Returns the key of the entry.
-    pub(crate) fn key(&self) -> &TKey {
-        self.0.key
-    }
-
     /// Attempts to insert the entry into a bucket.
     pub(crate) fn insert(self, value: TVal, status: NodeStatus) -> InsertResult<TKey> {
         self.0.bucket.insert(
diff --git a/protocols/kad/src/lib.rs b/protocols/kad/src/lib.rs
index dd9f7f56f30..4f1c7f0f7ec 100644
--- a/protocols/kad/src/lib.rs
+++ b/protocols/kad/src/lib.rs
@@ -33,9 +33,6 @@
 //! existing nodes in the kademlia network cannot obtain the listen addresses
 //! of nodes querying them, and thus will not be able to add them to their routing table.
 
-// TODO: we allow dead_code for now because this library contains a lot of unused code that will
-//       be useful later for record store
-#![allow(dead_code)]
 #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
 
 mod record_priv;
diff --git a/protocols/kad/src/query.rs b/protocols/kad/src/query.rs
index 6cc158619f5..20faff7721c 100644
--- a/protocols/kad/src/query.rs
+++ b/protocols/kad/src/query.rs
@@ -326,15 +326,6 @@ impl<TInner> Query<TInner> {
         }
     }
 
-    /// Checks whether the query is currently waiting for a result from `peer`.
-    pub(crate) fn is_waiting(&self, peer: &PeerId) -> bool {
-        match &self.peer_iter {
-            QueryPeerIter::Closest(iter) => iter.is_waiting(peer),
-            QueryPeerIter::ClosestDisjoint(iter) => iter.is_waiting(peer),
-            QueryPeerIter::Fixed(iter) => iter.is_waiting(peer),
-        }
-    }
-
     /// Advances the state of the underlying peer iterator.
     fn next(&mut self, now: Instant) -> PeersIterState<'_> {
         let state = match &mut self.peer_iter {
diff --git a/protocols/kad/src/query/peers/closest.rs b/protocols/kad/src/query/peers/closest.rs
index a9011803e73..01155b7f010 100644
--- a/protocols/kad/src/query/peers/closest.rs
+++ b/protocols/kad/src/query/peers/closest.rs
@@ -788,6 +788,7 @@ mod tests {
         QuickCheck::new().tests(10).quickcheck(prop as fn(_))
     }
 
+    #[test]
     fn stalled_at_capacity() {
         fn prop(mut iter: ClosestPeersIter) {
             iter.state = State::Stalled;
diff --git a/protocols/kad/src/query/peers/closest/disjoint.rs b/protocols/kad/src/query/peers/closest/disjoint.rs
index 3906b65b0af..151e26f69f1 100644
--- a/protocols/kad/src/query/peers/closest/disjoint.rs
+++ b/protocols/kad/src/query/peers/closest/disjoint.rs
@@ -31,7 +31,6 @@ use std::{
 /// Wraps around a set of [`ClosestPeersIter`], enforcing a disjoint discovery
 /// path per configured parallelism according to the S/Kademlia paper.
 pub(crate) struct ClosestDisjointPeersIter {
-    config: ClosestPeersIterConfig,
     target: KeyBytes,
 
     /// The set of wrapped [`ClosestPeersIter`].
@@ -51,6 +50,7 @@ pub(crate) struct ClosestDisjointPeersIter {
 
 impl ClosestDisjointPeersIter {
     /// Creates a new iterator with a default configuration.
+    #[cfg(test)]
     pub(crate) fn new<I>(target: KeyBytes, known_closest_peers: I) -> Self
     where
         I: IntoIterator<Item = Key<PeerId>>,
@@ -88,7 +88,6 @@ impl ClosestDisjointPeersIter {
         let iters_len = iters.len();
 
         ClosestDisjointPeersIter {
-            config,
             target: target.into(),
             iters,
             iter_order: (0..iters_len)
@@ -190,10 +189,6 @@ impl ClosestDisjointPeersIter {
         updated
     }
 
-    pub(crate) fn is_waiting(&self, peer: &PeerId) -> bool {
-        self.iters.iter().any(|i| i.is_waiting(peer))
-    }
-
     pub(crate) fn next(&mut self, now: Instant) -> PeersIterState<'_> {
         let mut state = None;
 
diff --git a/protocols/kad/src/query/peers/fixed.rs b/protocols/kad/src/query/peers/fixed.rs
index 1169feee87f..50a969380a3 100644
--- a/protocols/kad/src/query/peers/fixed.rs
+++ b/protocols/kad/src/query/peers/fixed.rs
@@ -115,10 +115,6 @@ impl FixedPeersIter {
         false
     }
 
-    pub(crate) fn is_waiting(&self, peer: &PeerId) -> bool {
-        self.peers.get(peer) == Some(&PeerState::Waiting)
-    }
-
     pub(crate) fn finish(&mut self) {
         if let State::Waiting { .. } = self.state {
             self.state = State::Finished