diff --git a/Cargo.lock b/Cargo.lock
index 98e333b6cc..0a1d9aad18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -202,7 +202,6 @@ dependencies = [
  "argon2",
  "basen",
  "bcrypt",
- "cfg-if",
  "chrono",
  "cuid2",
  "emojis",
diff --git a/Cargo.toml b/Cargo.toml
index 3ada688b7f..74d032aeae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,6 @@ napi-build = "2.1.3"
 argon2 = "0.5.3"
 basen = "0.1.0"
 bcrypt = "0.15.1"
-cfg-if = "1.0.0"
 chrono = "0.4.38"
 convert_case = "0.6.0"
 cuid2 = "0.1.2"
diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml
index eb0fa82631..5fcf7550dd 100644
--- a/packages/backend-rs/Cargo.toml
+++ b/packages/backend-rs/Cargo.toml
@@ -47,7 +47,6 @@ url = { workspace = true }
 urlencoding = { workspace = true }
 
 [dev-dependencies]
-cfg-if = { workspace = true }
 pretty_assertions = { workspace = true }
 
 [build-dependencies]
diff --git a/packages/backend-rs/src/database/cache.rs b/packages/backend-rs/src/database/cache.rs
index cbc7a60ff6..0503415481 100644
--- a/packages/backend-rs/src/database/cache.rs
+++ b/packages/backend-rs/src/database/cache.rs
@@ -2,10 +2,13 @@ use crate::database::{redis_conn, redis_key};
 use redis::{Commands, RedisError};
 use serde::{Deserialize, Serialize};
 
-#[derive(strum::Display)]
+#[derive(strum::Display, Debug)]
 pub enum Category {
     #[strum(serialize = "fetchUrl")]
     FetchUrl,
+    #[cfg(test)]
+    #[strum(serialize = "usedOnlyForTesting")]
+    Test,
 }
 
 #[derive(thiserror::Error, Debug)]
@@ -18,12 +21,19 @@ pub enum Error {
     DeserializeError(#[from] rmp_serde::decode::Error),
 }
 
+#[inline]
+fn prefix_key(key: &str) -> String {
+    redis_key(format!("cache:{}", key))
+}
+
+#[inline]
 fn categorize(category: Category, key: &str) -> String {
     format!("{}:{}", category, key)
 }
 
-fn prefix_key(key: &str) -> String {
-    redis_key(format!("cache:{}", key))
+#[inline]
+fn wildcard(category: Category) -> String {
+    prefix_key(&categorize(category, "*"))
 }
 
 pub fn set<V: for<'a> Deserialize<'a> + Serialize>(
@@ -71,11 +81,19 @@ pub fn delete_one(category: Category, key: &str) -> Result<(), Error> {
     delete(&categorize(category, key))
 }
 
-// TODO: set_all(), get_all(), delete_all()
+pub fn delete_all(category: Category) -> Result<(), Error> {
+    let mut redis = redis_conn()?;
+    let keys: Vec<Vec<u8>> = redis.keys(wildcard(category))?;
+    Ok(redis.del(keys)?)
+}
+
+// TODO: set_all(), get_all()
 
 #[cfg(test)]
 mod unit_test {
-    use super::{get, set};
+    use crate::database::cache::delete_one;
+
+    use super::{delete_all, get, get_one, set, set_one, Category::Test};
     use pretty_assertions::assert_eq;
 
     #[test]
@@ -121,4 +139,35 @@ mod unit_test {
         assert!(expired_value_2.is_none());
         assert!(expired_value_3.is_none());
     }
+
+    #[test]
+    fn use_category() {
+        let key_1 = "fire";
+        let key_2 = "fish";
+        let key_3 = "awawa";
+
+        let value_1 = "hello".to_string();
+        let value_2 = 998244353u32;
+        let value_3 = 'あ';
+
+        set_one(Test, key_1, &value_1, 5 * 60).unwrap();
+        set_one(Test, key_2, &value_2, 5 * 60).unwrap();
+        set_one(Test, key_3, &value_3, 5 * 60).unwrap();
+
+        assert_eq!(get_one::<String>(Test, key_1).unwrap().unwrap(), value_1);
+        assert_eq!(get_one::<u32>(Test, key_2).unwrap().unwrap(), value_2);
+        assert_eq!(get_one::<char>(Test, key_3).unwrap().unwrap(), value_3);
+
+        delete_one(Test, key_1).unwrap();
+
+        assert!(get_one::<String>(Test, key_1).unwrap().is_none());
+        assert!(get_one::<u32>(Test, key_2).unwrap().is_some());
+        assert!(get_one::<char>(Test, key_3).unwrap().is_some());
+
+        delete_all(Test).unwrap();
+
+        assert!(get_one::<String>(Test, key_1).unwrap().is_none());
+        assert!(get_one::<u32>(Test, key_2).unwrap().is_none());
+        assert!(get_one::<char>(Test, key_3).unwrap().is_none());
+    }
 }
diff --git a/packages/backend-rs/src/misc/get_image_size.rs b/packages/backend-rs/src/misc/get_image_size.rs
index c74b70e603..4cab76b8ad 100644
--- a/packages/backend-rs/src/misc/get_image_size.rs
+++ b/packages/backend-rs/src/misc/get_image_size.rs
@@ -123,20 +123,9 @@ mod unit_test {
         let gif_url = "https://firefish.dev/firefish/firefish/-/raw/b9c3dfbd3d473cb2cee20c467eeae780bc401271/packages/backend/test/resources/anime.gif";
         let mp3_url = "https://firefish.dev/firefish/firefish/-/blob/5891a90f71a8b9d5ea99c683ade7e485c685d642/packages/backend/assets/sounds/aisha/1.mp3";
 
-        cfg_if::cfg_if! {
-            if #[cfg(not(feature = "ci"))] {
-                // Delete caches in case you run this test multiple times
-                cache::delete_one(cache::Category::FetchUrl, png_url_1).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, png_url_2).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, png_url_3).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, rotated_jpeg_url).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, webp_url_1).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, webp_url_2).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, ico_url).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, gif_url).unwrap();
-                cache::delete_one(cache::Category::FetchUrl, mp3_url).unwrap();
-            }
-        }
+        // Delete caches in case you run this test multiple times
+        #[cfg(not(feature = "ci"))]
+        cache::delete_all(cache::Category::FetchUrl).unwrap();
 
         let png_size_1 = ImageSize {
             width: 1024,
diff --git a/packages/backend-rs/src/misc/latest_version.rs b/packages/backend-rs/src/misc/latest_version.rs
index 9e237aff4b..273a953296 100644
--- a/packages/backend-rs/src/misc/latest_version.rs
+++ b/packages/backend-rs/src/misc/latest_version.rs
@@ -79,11 +79,8 @@ mod unit_test {
 
     #[tokio::test]
     async fn check_version() {
-        cfg_if::cfg_if! {
-            if #[cfg(not(feature = "ci"))] {
-                cache::delete_one(cache::Category::FetchUrl, UPSTREAM_PACKAGE_JSON_URL).unwrap();
-            }
-        }
+        #[cfg(not(feature = "ci"))]
+        cache::delete_one(cache::Category::FetchUrl, UPSTREAM_PACKAGE_JSON_URL).unwrap();
 
         // fetch from firefish.dev
         validate_version(latest_version().await.unwrap());