diff --git a/Cargo.toml b/Cargo.toml
index a61b7992..567aace2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2021"
 
 [features]
 default = ["prometheus"]
-prometheus = ["prometheus/push", "prometheus/process"]
+prometheus = ["dep:prometheus", "prometheus/push", "prometheus/process"]
 # Enable integration tests with a running TiKV and PD instance.
 # Use $PD_ADDRS, comma separated, to set the addresses the tests use.
 integration-tests = []
@@ -34,7 +34,7 @@ futures = { version = "0.3" }
 lazy_static = "1"
 log = "0.4"
 pin-project = "1"
-prometheus = { version = "0.13", default-features = false }
+prometheus = { version = "0.13", default-features = false, optional = true }
 prost = "0.12"
 rand = "0.8"
 regex = "1"
diff --git a/src/lib.rs b/src/lib.rs
index 60dc2956..065c8ccb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -107,6 +107,7 @@ mod pd;
 mod proto;
 mod region;
 mod region_cache;
+#[cfg(feature = "prometheus")]
 mod stats;
 mod store;
 mod timestamp;
diff --git a/src/pd/retry.rs b/src/pd/retry.rs
index c9ccf1e1..bfd47b86 100644
--- a/src/pd/retry.rs
+++ b/src/pd/retry.rs
@@ -20,6 +20,7 @@ use crate::proto::pdpb::{self};
 use crate::region::RegionId;
 use crate::region::RegionWithLeader;
 use crate::region::StoreId;
+#[cfg(feature = "prometheus")]
 use crate::stats::pd_stats;
 use crate::Error;
 use crate::Result;
@@ -75,15 +76,22 @@ impl<Cl> RetryClient<Cl> {
 
 macro_rules! retry_core {
     ($self: ident, $tag: literal, $call: expr) => {{
+        #[cfg(feature = "prometheus")]
         let stats = pd_stats($tag);
         let mut last_err = Ok(());
         for _ in 0..LEADER_CHANGE_RETRY {
             let res = $call;
 
+            #[cfg(feature = "prometheus")]
             match stats.done(res) {
                 Ok(r) => return Ok(r),
                 Err(e) => last_err = Err(e),
             }
+            #[cfg(not(feature = "prometheus"))]
+            match res {
+                Ok(r) => return Ok(r),
+                Err(e) => last_err = Err(e),
+            }
 
             let mut reconnect_count = MAX_REQUEST_COUNT;
             while let Err(e) = $self.reconnect(RECONNECT_INTERVAL_SEC).await {
diff --git a/src/request/plan.rs b/src/request/plan.rs
index ffff6c24..44c5f62b 100644
--- a/src/request/plan.rs
+++ b/src/request/plan.rs
@@ -21,6 +21,7 @@ use crate::request::shard::HasNextBatch;
 use crate::request::NextBatch;
 use crate::request::Shardable;
 use crate::request::{KvRequest, StoreRequest};
+#[cfg(feature = "prometheus")]
 use crate::stats::tikv_stats;
 use crate::store::HasRegionError;
 use crate::store::HasRegionErrors;
@@ -60,6 +61,7 @@ impl<Req: KvRequest> Plan for Dispatch<Req> {
     type Result = Req::Response;
 
     async fn execute(&self) -> Result<Self::Result> {
+        #[cfg(feature = "prometheus")]
         let stats = tikv_stats(self.request.label());
         let result = self
             .kv_client
@@ -67,6 +69,7 @@ impl<Req: KvRequest> Plan for Dispatch<Req> {
             .expect("Unreachable: kv_client has not been initialised in Dispatch")
             .dispatch(&self.request)
             .await;
+        #[cfg(feature = "prometheus")]
         let result = stats.done(result);
         result.map(|r| {
             *r.downcast()