diff --git a/response_filesystem_cache.info.yml b/response_filesystem_cache.info.yml
index ed86bcd..2498af4 100644
--- a/response_filesystem_cache.info.yml
+++ b/response_filesystem_cache.info.yml
@@ -1,4 +1,4 @@
 name: 'Response Filesystem Cache'
 type: module
 description: 'Intercepts arbitrary responses, dynamically determines MIME types, and caches them as static files in the filesystem.'
-core_version_requirement: ^10 || ^11
\ No newline at end of file
+core_version_requirement: ^10.3 || ^11 || ^12
\ No newline at end of file
diff --git a/response_filesystem_cache.module b/response_filesystem_cache.module
index 03e2c10..0c4e010 100644
--- a/response_filesystem_cache.module
+++ b/response_filesystem_cache.module
@@ -1,38 +1,18 @@
 <?php
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\response_filesystem_cache\Hook\ResponseFilesystemCacheHooks;
+
 /**
  * @file
  * Primary module hooks for Response Filesystem Cache module.
  */
-
 /**
  * Implements hook_cache_flush().
  * Clears the physical static files whenever Drupal caches are cleared.
  */
-function response_filesystem_cache_cache_flush(): void {
-  $file_system = \Drupal::service('file_system');
-  $mapping_manager = \Drupal::service('response_filesystem_cache.mapping_manager');
-
-  foreach ($mapping_manager->getMappings() as $map) {
-    if (!empty($map['uri_prefix']) && str_starts_with($map['uri_prefix'], 'public://')) {
-      // Because we stripped trailing slashes in the mapping manager,
-      // we can isolate the highest level directory for this mapping.
-
-      // If the map was strictly file-based (e.g. public://api.json), get the directory.
-      // Usually, it's a directory structure.
-      $uri_dir = $map['uri_prefix'];
-
-      if (is_dir($uri_dir)) {
-        try {
-          $file_system->deleteRecursive($uri_dir);
-        }
-        catch (\Exception $e) {
-          \Drupal::logger('response_filesystem_cache')->error('Failed to clear static file cache at @dir: @message', [
-            '@dir' => $uri_dir,
-            '@message' => $e->getMessage(),
-          ]);
-        }
-      }
-    }
-  }
-}
\ No newline at end of file
+#[LegacyHook]
+function response_filesystem_cache_cache_flush(): void
+{
+    \Drupal::service(ResponseFilesystemCacheHooks::class)->cacheFlush();
+}
diff --git a/response_filesystem_cache.services.yml b/response_filesystem_cache.services.yml
index 77a35b0..910cfcc 100644
--- a/response_filesystem_cache.services.yml
+++ b/response_filesystem_cache.services.yml
@@ -14,4 +14,7 @@ services:
       - '@response_filesystem_cache.mapping_manager'
       - '@router.no_access_checks'
     tags:
-      - { name: event_subscriber }
\ No newline at end of file
+      - { name: event_subscriber }
+  Drupal\response_filesystem_cache\Hook\ResponseFilesystemCacheHooks:
+    class: Drupal\response_filesystem_cache\Hook\ResponseFilesystemCacheHooks
+    autowire: true
diff --git a/src/EventSubscriber/ResponseFilesystemCacheSubscriber.php b/src/EventSubscriber/ResponseFilesystemCacheSubscriber.php
index 46dccb0..d0aebf7 100644
--- a/src/EventSubscriber/ResponseFilesystemCacheSubscriber.php
+++ b/src/EventSubscriber/ResponseFilesystemCacheSubscriber.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\response_filesystem_cache\EventSubscriber;
 
+use Drupal\Component\Utility\DeprecationHelper;
+use Drupal\Core\File\FileExists;
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\File\FileUrlGeneratorInterface;
 use Drupal\Core\Routing\TrustedRedirectResponse;
@@ -154,7 +156,7 @@ class ResponseFilesystemCacheSubscriber implements EventSubscriberInterface {
           $dir = $this->fileSystem->dirname($uri);
 
           $this->fileSystem->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
-          $this->fileSystem->saveData($response->getContent(), $uri, FileSystemInterface::EXISTS_REPLACE);
+          $this->fileSystem->saveData($response->getContent(), $uri, DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '10.3.0', fn() => FileExists::Replace, fn() => FileSystemInterface::EXISTS_REPLACE));
 
           $event->setResponse($response);
         }
diff --git a/src/Hook/ResponseFilesystemCacheHooks.php b/src/Hook/ResponseFilesystemCacheHooks.php
new file mode 100644
index 0000000..4fcf7d5
--- /dev/null
+++ b/src/Hook/ResponseFilesystemCacheHooks.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\response_filesystem_cache\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+/**
+ * Hook implementations for response_filesystem_cache.
+ */
+class ResponseFilesystemCacheHooks
+{
+    /**
+     * @file
+     * Primary module hooks for Response Filesystem Cache module.
+     */
+    /**
+     * Implements hook_cache_flush().
+     * Clears the physical static files whenever Drupal caches are cleared.
+     */
+    #[Hook('cache_flush')]
+    public function cacheFlush(): void
+    {
+        $file_system = \Drupal::service('file_system');
+        $mapping_manager = \Drupal::service('response_filesystem_cache.mapping_manager');
+        foreach ($mapping_manager->getMappings() as $map) {
+            if (!empty($map['uri_prefix']) && str_starts_with($map['uri_prefix'], 'public://')) {
+                // Because we stripped trailing slashes in the mapping manager,
+                // we can isolate the highest level directory for this mapping.
+                // If the map was strictly file-based (e.g. public://api.json), get the directory.
+                // Usually, it's a directory structure.
+                $uri_dir = $map['uri_prefix'];
+                if (is_dir($uri_dir)) {
+                    try {
+                        $file_system->deleteRecursive($uri_dir);
+                    } catch (\Exception $e) {
+                        \Drupal::logger('response_filesystem_cache')->error('Failed to clear static file cache at @dir: @message', [
+                            '@dir' => $uri_dir,
+                            '@message' => $e->getMessage(),
+                        ]);
+                    }
+                }
+            }
+        }
+    }
+}
