diff --git a/src/database/key_value/media.rs b/src/database/key_value/media.rs
index da7162b6..dcafc74e 100644
--- a/src/database/key_value/media.rs
+++ b/src/database/key_value/media.rs
@@ -1,4 +1,5 @@
 use ruma::api::client::error::ErrorKind;
+use tracing::debug;
 
 use crate::{
     database::KeyValueDatabase,
@@ -40,14 +41,46 @@ impl service::media::Data for KeyValueDatabase {
     }
 
     fn delete_file_mxc(&self, mxc: String) -> Result<()> {
-        let mut key = mxc.as_bytes().to_vec();
-        key.push(0xff);
+        debug!("MXC URI: {:?}", mxc);
 
-        self.mediaid_file.remove(&key)?;
+        let mut prefix = mxc.as_bytes().to_vec();
+        prefix.push(0xff);
+
+        debug!("MXC db prefix: {:?}", prefix);
+
+        for (key, _) in self.mediaid_file.scan_prefix(prefix) {
+            debug!("Deleting key: {:?}", key);
+            self.mediaid_file.remove(&key)?;
+        }
+        //return Err(Error::bad_database("Media not found."));
 
         Ok(())
     }
 
+    /// Searches for all files with the given MXC (e.g. thumbnail and original image)
+    fn search_mxc_metadata_prefix(&self, mxc: String) -> Result<Vec<Vec<u8>>> {
+        debug!("MXC URI: {:?}", mxc);
+
+        let mut prefix = mxc.as_bytes().to_vec();
+        prefix.push(0xff);
+
+        let mut keys: Vec<Vec<u8>> = vec![];
+
+        for (key, _) in self.mediaid_file.scan_prefix(prefix) {
+            keys.push(key);
+        }
+
+        if keys.is_empty() {
+            return Err(Error::bad_database(
+                "Failed to find any keys in database with the provided MXC.",
+            ));
+        }
+
+        debug!("Got the following keys: {:?}", keys);
+
+        Ok(keys)
+    }
+
     fn search_file_metadata(
         &self,
         mxc: String,
diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs
index 73977f3b..0807bda2 100644
--- a/src/service/admin/mod.rs
+++ b/src/service/admin/mod.rs
@@ -27,8 +27,8 @@ use ruma::{
         },
         TimelineEventType,
     },
-    EventId, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId,
-    RoomVersionId, ServerName, UserId,
+    EventId, MxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId,
+    RoomOrAliasId, RoomVersionId, ServerName, UserId,
 };
 use serde_json::value::to_raw_value;
 use tokio::sync::{mpsc, Mutex};
@@ -69,6 +69,10 @@ enum AdminCommand {
     /// - Commands for managing the server
     Server(ServerCommand),
 
+    #[command(subcommand)]
+    /// - Commands for managing media
+    Media(MediaCommand),
+
     #[command(subcommand)]
     // TODO: should i split out debug commands to a separate thing? the
     // debug commands seem like they could fit in the other categories fine
@@ -77,6 +81,16 @@ enum AdminCommand {
     Debug(DebugCommand),
 }
 
+#[cfg_attr(test, derive(Debug))]
+#[derive(Subcommand)]
+enum MediaCommand {
+    /// - Deletes a single media file from our database and on the filesystem via a single MXC URI
+    Delete {
+        /// The MXC URI to delete
+        mxc: Box<MxcUri>,
+    },
+}
+
 #[cfg_attr(test, derive(Debug))]
 #[derive(Subcommand)]
 enum AppserviceCommand {
@@ -606,6 +620,16 @@ impl Service {
                     }
                 }
             },
+            AdminCommand::Media(command) => match command {
+                MediaCommand::Delete { mxc } => {
+                    debug!("Got MXC URI: {}", mxc);
+                    services().media.delete(mxc.to_string()).await?;
+
+                    return Ok(RoomMessageEventContent::text_plain(
+                        "Deleted the MXC from our database and on our filesystem.",
+                    ));
+                }
+            },
             AdminCommand::Users(command) => match command {
                 UserCommand::List => match services().users.list_local_users() {
                     Ok(users) => {
diff --git a/src/service/media/data.rs b/src/service/media/data.rs
index 667267f6..0404b548 100644
--- a/src/service/media/data.rs
+++ b/src/service/media/data.rs
@@ -20,6 +20,8 @@ pub trait Data: Send + Sync {
         height: u32,
     ) -> Result<(Option<String>, Option<String>, Vec<u8>)>;
 
+    fn search_mxc_metadata_prefix(&self, mxc: String) -> Result<Vec<Vec<u8>>>;
+
     fn remove_url_preview(&self, url: &str) -> Result<()>;
 
     fn set_url_preview(
diff --git a/src/service/media/mod.rs b/src/service/media/mod.rs
index 7ecd7519..9c3d4a86 100644
--- a/src/service/media/mod.rs
+++ b/src/service/media/mod.rs
@@ -8,7 +8,7 @@ use std::{
 
 pub(crate) use data::Data;
 use serde::Serialize;
-use tracing::{debug, error, warn};
+use tracing::{debug, error};
 
 use crate::{services, Error, Result};
 use image::imageops::FilterType;
@@ -93,45 +93,30 @@ impl Service {
 
     /// Deletes a file in the database and from the media directory via an MXC
     pub async fn delete(&self, mxc: String) -> Result<()> {
-        if let Ok(filemeta) = self.get(mxc.clone()).await {
-            match filemeta {
-                Some(filemeta) => {
-                    debug!("Got file metadata: {:?}", filemeta);
-                    let file_key = filemeta.file;
-                    debug!("File key from file metadata: {:?}", file_key);
+        if let Ok(keys) = self.db.search_mxc_metadata_prefix(mxc.clone()) {
+            for key in keys {
+                let file_path = if cfg!(feature = "sha256_media") {
+                    services().globals.get_media_file_new(&key)
+                } else {
+                    #[allow(deprecated)]
+                    services().globals.get_media_file(&key)
+                };
+                debug!("Got local file path: {:?}", file_path);
 
-                    let file_path = if cfg!(feature = "sha256_media") {
-                        services().globals.get_media_file_new(&file_key)
-                    } else {
-                        #[allow(deprecated)]
-                        services().globals.get_media_file(&file_key)
-                    };
-                    debug!("Got local file path: {:?}", file_path);
+                debug!(
+                    "Deleting local file {:?} from filesystem, original MXC: {}",
+                    file_path, mxc
+                );
+                tokio::fs::remove_file(file_path).await?;
 
-                    debug!(
-                        "Deleting local file {:?} from filesystem, original MXC: {mxc}",
-                        file_path
-                    );
-                    tokio::fs::remove_file(file_path).await?;
-
-                    debug!("Deleting MXC {mxc} from database");
-                    self.db.delete_file_mxc(mxc)?;
-
-                    Ok(())
-                }
-                None => {
-                    warn!(
-                        "MXC {mxc} does not exist in our database or file in MXC does not exist."
-                    );
-                    Err(Error::bad_database(
-                        "MXC does not exist in our database or file in MXC does not exist.",
-                    ))
-                }
+                debug!("Deleting MXC {mxc} from database");
+                self.db.delete_file_mxc(mxc.clone())?;
             }
+
+            Ok(())
         } else {
-            // we shouldn't get to this point as this is failing to actually attempt to get the file metadata (Result)
-            error!("Failed getting file metadata for MXC \"{mxc}\" in database (does not exist or database issue?)");
-            Err(Error::bad_database("Failed getting file metadata via MXC in database (does not exist or database issue?)"))
+            error!("Failed to find any media keys for MXC \"{mxc}\" in our database (MXC does not exist)");
+            Err(Error::bad_database("Failed to find any media keys for the provided MXC in our database (MXC does not exist)"))
         }
     }