diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index bf081e4c42afe8cefd44feff48d105f28816c803..f8126f62264bba005fe788c1f7b614608278c907 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -32,7 +32,7 @@ phpcs:
 # Uncomment the lines below if you want to override any of the variables. The following is just an example.
 ################
 variables:
-  OPT_IN_TEST_PREVIOUS_MAJOR: '1'
+  OPT_IN_TEST_NEXT_MAJOR: '1'
   OPT_IN_TEST_NEXT_MINOR: '1'
   _CSPELL_WORDS: 'Unblockmanager,batigolix,Doesborg,fabianderijk,Rijk'
 #   SKIP_ESLINT: '1'
diff --git a/composer.json b/composer.json
index 7b61bd6f7df1f4aec5518d41ba34e6b07c0ce620..ef8e0701642b198158b1f9e24f1c5cf6565e1508 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
     "type": "drupal-module",
     "license": "GPL-2.0-or-later",
     "require": {
-        "drupal/core": "^9 || ^10"
+        "drupal/core": "^10.2 || ^11"
     },
     "extra": {
         "drush": {
diff --git a/flood_control.info.yml b/flood_control.info.yml
index a60e4eb4733722008e91340c02c721e6b56070b7..ede7f0c48e9b283e2a03335e5be971b816f1ecb8 100644
--- a/flood_control.info.yml
+++ b/flood_control.info.yml
@@ -3,4 +3,4 @@ description: "Allows configuring hidden flood control options and unblocking IP
 configure: flood_control.settings
 package: 'Administration'
 type: module
-core_version_requirement: ^9 || ^10
+core_version_requirement: ^10.2 || ^11
diff --git a/flood_control.install b/flood_control.install
index 3320f9120b80711a25e189eac02d09708771a79f..1f05d88dba450a6df79736168d8f534abc736677 100644
--- a/flood_control.install
+++ b/flood_control.install
@@ -6,12 +6,14 @@
  */
 
 use Drupal\user\Entity\Role;
+use Drupal\user\RoleInterface;
 
 /**
  * Assign newly added permissions to the appropriate roles.
  */
 function flood_control_update_9201() {
-  $roles = user_role_names(FALSE, 'access flood unblock');
+  $names = array_filter(Role::loadMultiple(), fn(RoleInterface $role) => $role->hasPermission('access flood unblock'));
+  $roles = array_map(fn(RoleInterface $role) => $role->label(), $names);
   foreach ($roles as $roleKey => $roleName) {
     user_role_grant_permissions($roleKey, [
       'administer flood unblock',
diff --git a/src/FloodUnblockManager.php b/src/FloodUnblockManager.php
deleted file mode 100755
index 8ade1f791ab2152e8c16d57cc468641938c4d758..0000000000000000000000000000000000000000
--- a/src/FloodUnblockManager.php
+++ /dev/null
@@ -1,235 +0,0 @@
-<?php
-
-namespace Drupal\flood_control;
-
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Flood\FloodInterface;
-use Drupal\Core\Logger\LoggerChannelFactoryInterface;
-use Drupal\Core\Messenger\MessengerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-
-/**
- * Provides Flood Unblock actions.
- */
-class FloodUnblockManager implements FloodUnblockManagerInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The Database Connection.
-   *
-   * @var \Drupal\Core\Database\Connection
-   */
-  protected $database;
-
-  /**
-   * The Entity Type Manager Interface.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The Flood Interface.
-   *
-   * @var \Drupal\Core\Flood\FloodInterface
-   */
-  protected $flood;
-
-  /**
-   * The Immutable Config.
-   *
-   * @var \Drupal\Core\Config\ImmutableConfig
-   */
-  protected $config;
-
-  /**
-   * The messenger.
-   *
-   * @var \Drupal\Core\Messenger\MessengerInterface
-   */
-  protected $messenger;
-
-  /**
-   * The logger factory.
-   *
-   * @var \Drupal\Core\Logger\LoggerChannelFactory
-   */
-  protected $loggerFactory;
-
-  /**
-   * FloodUnblockAdminForm constructor.
-   *
-   * @param \Drupal\Core\Database\Connection $database
-   *   The database connection.
-   * @param \Drupal\Core\Flood\FloodInterface $flood
-   *   The flood interface.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
-   *   The Config Factory Interface.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
-   *   The Entity Type Manager Interface.
-   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
-   *   The Messenger Interface.
-   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
-   *   The logger factory.
-   */
-  public function __construct(Connection $database, FloodInterface $flood, ConfigFactoryInterface $configFactory, EntityTypeManagerInterface $entityTypeManager, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory) {
-    $this->database = $database;
-    $this->flood = $flood;
-    $this->entityTypeManager = $entityTypeManager;
-    $this->config = $configFactory->get('user.flood');
-    $this->messenger = $messenger;
-    $this->loggerFactory = $logger_factory->get('flood_control');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fetchIdentifiers($results) {
-    $identifiers = [];
-
-    foreach ($results as $result) {
-
-      // Sets ip as default value and adds to identifiers array.
-      $identifiers[$result] = $result;
-
-      // Sets location as value and adds to identifiers array.
-      if (function_exists('smart_ip_get_location')) {
-        $location = smart_ip_get_location($result);
-        $location_string = sprintf(" (%s %s %s)", $location['city'], $location['region'], $location['country_code']);
-        $identifiers[$result] = "$location_string ($result)";
-      }
-
-      // Sets link to user as value and adds to identifiers array.
-      $parts = explode('-', $result);
-      if (isset($parts[0]) && isset($parts[1])) {
-        $uid = $parts[0];
-
-        /** @var \Drupal\user\Entity\User $user */
-        $user = $this->entityTypeManager->getStorage('user')
-          ->load($uid);
-        if (isset($user)) {
-          $user_link = $user->toLink($user->getAccountName());
-        }
-        else {
-          $user_link = $this->t('Deleted user: @user', ['@user' => $uid]);
-        }
-        $identifiers[$result] = $user_link;
-      }
-
-    }
-    return $identifiers;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function floodUnblockClearEvent($fid) {
-    $txn = $this->database->startTransaction('flood_unblock_clear');
-    try {
-      $query = $this->database->delete('flood')
-        ->condition('fid', $fid);
-      $success = $query->execute();
-      if ($success) {
-        $this->messenger->addMessage($this->t('Flood entries cleared.'), 'status', FALSE);
-      }
-    }
-    catch (\Exception $e) {
-      // Something went wrong somewhere, so roll back now.
-      $txn->rollback();
-
-      // Log the exception to drupal.
-      $this->loggerFactory->error($e);
-      $this->messenger->addMessage($this->t('Error: @error', ['@error' => (string) $e]), 'error');
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEvents() {
-    return [
-      'user.failed_login_ip' => [
-        'type' => 'ip',
-        'label' => $this->t('User failed login IP'),
-      ],
-      'user.failed_login_user' => [
-        'type' => 'user',
-        'label' => $this->t('User failed login user'),
-      ],
-      'user.http_login' => [
-        'type' => 'user',
-        'label' => $this->t('User failed http login'),
-      ],
-      'user.password_request_ip' => [
-        'type' => 'user',
-        'label' => $this->t('User failed password request IP'),
-      ],
-      'user.password_request_user' => [
-        'type' => 'user',
-        'label' => $this->t('User failed password request user'),
-      ],
-    ];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEventLabel($event) {
-    $event_mapping = $this->getEvents();
-    if (array_key_exists($event, $event_mapping)) {
-      return $event_mapping[$event]['label'];
-    }
-
-    return ucfirst(str_replace(['.', '_'], ' ', $event));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEventType($event) {
-    $event_mapping = $this->getEvents();
-    if (array_key_exists($event, $event_mapping)) {
-      return $event_mapping[$event]['type'];
-    }
-
-    $parts = explode('.', $event);
-    return $parts[0];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isBlocked($identifier, $event) {
-    $type = $this->getEventType($event);
-    switch ($type) {
-      case 'user':
-        return !$this->flood->isAllowed($event, $this->config->get('user_limit'), $this->config->get('user_window'), $identifier);
-
-      case 'ip':
-        return !$this->flood->isAllowed($event, $this->config->get('ip_limit'), $this->config->get('ip_window'), $identifier);
-    }
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEventIds($event, $identifier = NULL) {
-    $event_ids = [];
-    $query = $this->database->select('flood', 'f');
-    $query->condition('event', $event);
-    if ($identifier) {
-      $query->condition('f.identifier', $identifier, 'LIKE');
-    }
-    $query->fields('f', ['fid']);
-    $result = $query->execute();
-    foreach ($result as $record) {
-      $event_ids[] = $record->fid;
-    }
-    return $event_ids;
-  }
-
-}
diff --git a/src/FloodUnblockManagerBase.php b/src/FloodUnblockManagerBase.php
index b3d3e9056d90c80ebb90eef04c1f3629cfc05910..8ca4b495d4f98ac79912aceae89d40b139292ba6 100644
--- a/src/FloodUnblockManagerBase.php
+++ b/src/FloodUnblockManagerBase.php
@@ -25,6 +25,13 @@ abstract class FloodUnblockManagerBase implements FloodUnblockManagerInterface {
    */
   protected $config;
 
+  /**
+   * The Entity Type Manager Interface.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
   /**
    * {@inheritdoc}
    */
diff --git a/src/FloodUnblockManagerDatabase.php b/src/FloodUnblockManagerDatabase.php
index 869769ac1b502e850c422fd7bd0ac3258610b3cc..7a08f0f8a2921ac28c453e55590261105042c989 100755
--- a/src/FloodUnblockManagerDatabase.php
+++ b/src/FloodUnblockManagerDatabase.php
@@ -21,6 +21,20 @@ class FloodUnblockManagerDatabase extends FloodUnblockManagerBase {
    */
   protected $database;
 
+  /**
+   * The Flood Service.
+   *
+   * @var \Drupal\Core\Flood\FloodInterface
+   */
+  protected $flood;
+
+  /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $config;
+
   /**
    * The Entity Type Manager Interface.
    *
diff --git a/src/Form/FloodControlSettingsForm.php b/src/Form/FloodControlSettingsForm.php
index 39fb8b76f5706ae665dcc79256ec14f967c265e7..573c403bbd9bc53afaeb20a1d23b23f533b5e6b8 100644
--- a/src/Form/FloodControlSettingsForm.php
+++ b/src/Form/FloodControlSettingsForm.php
@@ -3,6 +3,7 @@
 namespace Drupal\flood_control\Form;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\Datetime\DateFormatterInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\ConfigFormBase;
@@ -32,8 +33,13 @@ class FloodControlSettingsForm extends ConfigFormBase {
   /**
    * {@inheritdoc}
    */
-  public function __construct(ConfigFactoryInterface $config_factory, DateFormatterInterface $dateFormatter, ModuleHandlerInterface $module_handler) {
-    parent::__construct($config_factory);
+  public function __construct(
+    ConfigFactoryInterface $configFactory,
+    TypedConfigManagerInterface $typedConfigManager,
+    DateFormatterInterface $dateFormatter,
+    ModuleHandlerInterface $module_handler,
+  ) {
+    parent::__construct($configFactory, $typedConfigManager);
     $this->dateFormatter = $dateFormatter;
     $this->moduleHandler = $module_handler;
   }
@@ -44,8 +50,9 @@ class FloodControlSettingsForm extends ConfigFormBase {
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('config.factory'),
+      $container->get('config.typed'),
       $container->get('date.formatter'),
-      $container->get('module_handler')
+      $container->get('module_handler'),
     );
   }
 
diff --git a/tests/src/Functional/FloodControlUiPageTest.php b/tests/src/Functional/FloodControlUiPageTest.php
index 66825eee441d091b729da50b4745f0010c97e77f..6c0447af1c026de8555984e1d10dcb0374d71179 100644
--- a/tests/src/Functional/FloodControlUiPageTest.php
+++ b/tests/src/Functional/FloodControlUiPageTest.php
@@ -4,6 +4,8 @@ namespace Drupal\Tests\flood_control\Functional;
 
 use Drupal\Tests\BrowserTestBase;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
 
 /**
  * Tests that the Flood control UI pages are reachable.
@@ -55,7 +57,7 @@ class FloodControlUiPageTest extends BrowserTestBase {
   /**
    * Create required user and other objects in order to run tests.
    */
-  public function setUp(): void {
+  protected function setUp(): void {
     parent::setUp();
 
     $this->adminUser = $this->drupalCreateUser([]);
@@ -69,6 +71,7 @@ class FloodControlUiPageTest extends BrowserTestBase {
     // Flood backends need a request object. Create a dummy one and insert it
     // to the container.
     $request = Request::createFromGlobals();
+    $request->setSession(new Session(new MockArraySessionStorage()));
     $this->container->get('request_stack')->push($request);
 
     // The flood table is opportunistically created during first use. In these