diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 9ec71ecede..ab5cbe67b9 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -59,6 +59,7 @@ void LogSettings() {
     log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
     log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue());
     log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
+    log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue());
     log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
     log_setting("Audio_OutputEngine", values.sink_id);
     log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
@@ -141,6 +142,7 @@ void RestoreGlobalState(bool is_powered_on) {
     values.use_assembly_shaders.SetGlobal(true);
     values.use_asynchronous_shaders.SetGlobal(true);
     values.use_fast_gpu_time.SetGlobal(true);
+    values.use_caches_gc.SetGlobal(true);
     values.bg_red.SetGlobal(true);
     values.bg_green.SetGlobal(true);
     values.bg_blue.SetGlobal(true);
diff --git a/src/common/settings.h b/src/common/settings.h
index 6198f2d9fd..a1c0bf3ad2 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -152,6 +152,7 @@ struct Values {
     Setting<bool> use_assembly_shaders;
     Setting<bool> use_asynchronous_shaders;
     Setting<bool> use_fast_gpu_time;
+    Setting<bool> use_caches_gc;
 
     Setting<float> bg_red;
     Setting<float> bg_green;
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index b4fa85c5b6..a8fb21d92c 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -350,9 +350,10 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
 
 template <class P>
 void BufferCache<P>::TickFrame() {
+    const bool enabled_gc = Settings::values.use_caches_gc.GetValue();
     SCOPE_EXIT({
-      ++frame_tick;
-      delayed_destruction_ring.Tick();
+        ++frame_tick;
+        delayed_destruction_ring.Tick();
     });
     // Calculate hits and shots and move hit bits to the right
     const u32 hits = std::reduce(uniform_cache_hits.begin(), uniform_cache_hits.end());
@@ -367,7 +368,7 @@ void BufferCache<P>::TickFrame() {
     const bool skip_preferred = hits * 256 < shots * 251;
     uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0;
 
-    const bool activate_gc = total_used_memory >= expected_memory;
+    const bool activate_gc = enabled_gc && total_used_memory >= expected_memory;
     if (!activate_gc) {
         return;
     }
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index 40c047ea19..e326cab71c 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -27,10 +27,10 @@ enum class ImageFlagBits : u32 {
     Picked = 1 << 7,      ///< Temporary flag to mark the image as picked
 
     // Garbage Collection Flags
-    BadOverlap = 1 << 8,     ///< This image overlaps other but doesn't fit, has higher
-                             ///< garbage collection priority
-    Alias = 1 << 9,          ///< This image has aliases and has priority on garbage
-                             ///< collection
+    BadOverlap = 1 << 8, ///< This image overlaps other but doesn't fit, has higher
+                         ///< garbage collection priority
+    Alias = 1 << 9,      ///< This image has aliases and has priority on garbage
+                         ///< collection
 };
 DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
 
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cf48f7b022..8685f44182 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -22,6 +22,7 @@
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/logging/log.h"
+#include "common/settings.h"
 #include "video_core/compatible_formats.h"
 #include "video_core/delayed_destruction_ring.h"
 #include "video_core/dirty_flags.h"
@@ -384,6 +385,15 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
 
 template <class P>
 void TextureCache<P>::TickFrame() {
+    const bool enabled_gc = Settings::values.use_caches_gc.GetValue();
+    if (!enabled_gc) {
+        // @Note(Blinkhawk): compile error with SCOPE_EXIT on msvc.
+        sentenced_images.Tick();
+        sentenced_framebuffers.Tick();
+        sentenced_image_view.Tick();
+        ++frame_tick;
+        return;
+    }
     const bool high_priority_mode = total_used_memory >= expected_memory;
     const bool aggressive_mode = total_used_memory >= critical_memory;
     const u64 ticks_to_destroy = high_priority_mode ? 60 : 100;
@@ -397,22 +407,20 @@ void TextureCache<P>::TickFrame() {
         }
         const auto [image_id, image] = *deletion_iterator;
         const bool is_alias = True(image->flags & ImageFlagBits::Alias);
-        if (is_alias && image->aliased_images.size() <= 1) {
-            ++deletion_iterator;
-            continue;
-        }
         const bool is_bad_overlap = True(image->flags & ImageFlagBits::BadOverlap);
         const bool must_download = image->IsSafeDownload();
-        const u64 ticks_needed = is_bad_overlap ? ticks_to_destroy >> 4 : ticks_to_destroy;
-        const bool should_care =
-            aggressive_mode || is_bad_overlap || is_alias || (high_priority_mode && !must_download);
+        bool should_care = is_bad_overlap || is_alias || (high_priority_mode && !must_download);
+        const u64 ticks_needed =
+            is_bad_overlap
+                ? ticks_to_destroy >> 4
+                : ((should_care && aggressive_mode) ? ticks_to_destroy >> 1 : ticks_to_destroy);
+        should_care |= aggressive_mode;
         if (should_care && image->frame_tick + ticks_needed < frame_tick) {
             if (is_bad_overlap) {
                 const bool overlap_check =
                     std::ranges::all_of(image->overlapping_images, [&](const ImageId& overlap_id) {
                         auto& overlap = slot_images[overlap_id];
-                        return (overlap.frame_tick >= image->frame_tick) &&
-                               (overlap.modification_tick > image->modification_tick);
+                        return overlap.frame_tick >= image->frame_tick;
                     });
                 if (!overlap_check) {
                     ++deletion_iterator;
@@ -420,23 +428,20 @@ void TextureCache<P>::TickFrame() {
                 }
             }
             if (!is_bad_overlap && must_download) {
-                if (is_alias) {
-                    const bool alias_check =
-                        std::ranges::all_of(image->aliased_images, [&](const AliasedImage& alias) {
-                            auto& alias_image = slot_images[alias.id];
-                            return (alias_image.frame_tick >= image->frame_tick) &&
-                                   (alias_image.modification_tick > image->modification_tick);
-                        });
-                    if (!alias_check) {
-                        ++deletion_iterator;
-                        continue;
-                    }
+                const bool alias_check =
+                    std::ranges::none_of(image->aliased_images, [&](const AliasedImage& alias) {
+                        auto& alias_image = slot_images[alias.id];
+                        return (alias_image.frame_tick < image->frame_tick) ||
+                               (alias_image.modification_tick < image->modification_tick);
+                    });
+
+                if (alias_check) {
+                    auto map = runtime.DownloadStagingBuffer(image->unswizzled_size_bytes);
+                    const auto copies = FullDownloadCopies(image->info);
+                    image->DownloadMemory(map, copies);
+                    runtime.Finish();
+                    SwizzleImage(gpu_memory, image->gpu_addr, image->info, copies, map.mapped_span);
                 }
-                auto map = runtime.DownloadStagingBuffer(image->unswizzled_size_bytes);
-                const auto copies = FullDownloadCopies(image->info);
-                image->DownloadMemory(map, copies);
-                runtime.Finish();
-                SwizzleImage(gpu_memory, image->gpu_addr, image->info, copies, map.mapped_span);
             }
             if (True(image->flags & ImageFlagBits::Tracked)) {
                 UntrackImage(*image);
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 916a227241..57843ac5a8 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -817,6 +817,7 @@ void Config::ReadRendererValues() {
                       QStringLiteral("use_asynchronous_shaders"), false);
     ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
                       true);
+    ReadSettingGlobal(Settings::values.use_caches_gc, QStringLiteral("use_caches_gc"), false);
     ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0);
     ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0);
     ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0);
@@ -1401,6 +1402,7 @@ void Config::SaveRendererValues() {
                        Settings::values.use_asynchronous_shaders, false);
     WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time,
                        true);
+    WriteSettingGlobal(QStringLiteral("use_caches_gc"), Settings::values.use_caches_gc, false);
     // Cast to double because Qt's written float values are not human-readable
     WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0);
     WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0);
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 35bf9c6be5..a9e611125d 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -30,6 +30,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
     ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
     ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
     ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
+    ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue());
     ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
 
     if (Settings::IsConfiguringGlobal()) {
@@ -62,6 +63,8 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
                                              ui->use_asynchronous_shaders,
                                              use_asynchronous_shaders);
+    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_caches_gc, ui->use_caches_gc,
+                                             use_caches_gc);
     ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
                                              ui->use_fast_gpu_time, use_fast_gpu_time);
 
@@ -101,6 +104,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
         ui->use_asynchronous_shaders->setEnabled(
             Settings::values.use_asynchronous_shaders.UsingGlobal());
         ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
+        ui->use_caches_gc->setEnabled(Settings::values.use_caches_gc.UsingGlobal());
         ui->anisotropic_filtering_combobox->setEnabled(
             Settings::values.max_anisotropy.UsingGlobal());
 
@@ -115,6 +119,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
                                             use_asynchronous_shaders);
     ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time,
                                             Settings::values.use_fast_gpu_time, use_fast_gpu_time);
+    ConfigurationShared::SetColoredTristate(ui->use_caches_gc, Settings::values.use_caches_gc,
+                                            use_caches_gc);
     ConfigurationShared::SetColoredComboBox(
         ui->gpu_accuracy, ui->label_gpu_accuracy,
         static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index e61b571c7f..9148aacf24 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -38,4 +38,5 @@ private:
     ConfigurationShared::CheckState use_assembly_shaders;
     ConfigurationShared::CheckState use_asynchronous_shaders;
     ConfigurationShared::CheckState use_fast_gpu_time;
+    ConfigurationShared::CheckState use_caches_gc;
 };
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 846a30586d..3566e9bfaf 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -103,6 +103,16 @@
           </property>
          </widget>
         </item>
+        <item>
+         <widget class="QCheckBox" name="use_caches_gc">
+          <property name="toolTip">
+           <string>Enables garbage collection for the GPU caches, this will try to keep VRAM within 3-4Gb and flush least used textures/buffers. This option may be unsafe on a few games</string>
+          </property>
+          <property name="text">
+           <string>Enable GPU caches garbage collection (unsafe)</string>
+          </property>
+         </widget>
+        </item>
         <item>
          <widget class="QWidget" name="af_layout" native="true">
           <layout class="QHBoxLayout" name="horizontalLayout_1">
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index efa1b1d18d..8399190626 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -227,6 +227,10 @@ use_asynchronous_gpu_emulation =
 # 0: Off, 1 (default): On
 use_vsync =
 
+# Whether to use garbage collection or not.
+# 0 (default): Off, 1: On
+use_caches_gc =
+
 # The clear color for the renderer. What shows up on the sides of the bottom screen.
 # Must be in range of 0.0-1.0. Defaults to 1.0 for all.
 bg_red =