diff --git a/ee/app/models/ee/namespace/root_storage_size.rb b/ee/app/models/ee/namespace/root_storage_size.rb
index 8e06118f93e8e38f2eea6a88097788df96d1e713..84e49062f1744d4ed3c90509418ae4190fd6186a 100644
--- a/ee/app/models/ee/namespace/root_storage_size.rb
+++ b/ee/app/models/ee/namespace/root_storage_size.rb
@@ -38,6 +38,14 @@ def limit
       end
     end
 
+    def remaining_storage_percentage
+      [(100 - usage_ratio * 100).floor, 0].max
+    end
+
+    def remaining_storage_size
+      [limit - current_size, 0].max
+    end
+
     def enforce_limit?
       return false if Date.current < ENFORCEMENT_DATE
       return false if root_namespace.opensource_plan?
diff --git a/ee/app/services/namespaces/storage/email_notification_service.rb b/ee/app/services/namespaces/storage/email_notification_service.rb
index b2d0c81bc86b07f8c2231952b7bc7fdc6f725711..aa3d4c8c8421b5e67ec8f661fd686c25e258e1db 100644
--- a/ee/app/services/namespaces/storage/email_notification_service.rb
+++ b/ee/app/services/namespaces/storage/email_notification_service.rb
@@ -42,8 +42,8 @@ def send_notification(level, namespace, root_storage_size)
         if level == :exceeded
           mailer.notify_out_of_storage(namespace, owner_emails)
         else
-          percentage = remaining_storage_percentage(root_storage_size)
-          size = remaining_storage_size(root_storage_size)
+          percentage = root_storage_size.remaining_storage_percentage
+          size = root_storage_size.remaining_storage_size
           mailer.notify_limit_warning(namespace, owner_emails, percentage, size)
         end
       end
@@ -51,14 +51,6 @@ def send_notification(level, namespace, root_storage_size)
       def update_notification_level(level, namespace)
         namespace.root_storage_statistics.update!(notification_level: level)
       end
-
-      def remaining_storage_percentage(root_storage_size)
-        (100 - root_storage_size.usage_ratio * 100).floor
-      end
-
-      def remaining_storage_size(root_storage_size)
-        root_storage_size.limit - root_storage_size.current_size
-      end
     end
   end
 end
diff --git a/ee/spec/models/ee/namespace/root_storage_size_spec.rb b/ee/spec/models/ee/namespace/root_storage_size_spec.rb
index e80cdac3963b6e37290c3e1c3acc3df29712283b..8c99d973b15b9376e40ed0a6b9b925e327ee08d2 100644
--- a/ee/spec/models/ee/namespace/root_storage_size_spec.rb
+++ b/ee/spec/models/ee/namespace/root_storage_size_spec.rb
@@ -3,6 +3,9 @@
 require 'spec_helper'
 
 RSpec.describe EE::Namespace::RootStorageSize, :saas do
+  include NamespaceStorageHelpers
+  using RSpec::Parameterized::TableSyntax
+
   let(:namespace) { create(:namespace) }
   let(:current_size) { 50.megabytes }
   let(:model) { described_class.new(namespace) }
@@ -149,6 +152,60 @@
     end
   end
 
+  describe '#remaining_storage_percentage' do
+    where(:limit, :used, :expected_percentage) do
+      0    | 0    | 100
+      0    | 100  | 100
+      100  | 0    | 100
+      100  | 200  | 0
+      1    | 0    | 100
+      100  | 10   | 90
+      100  | 77   | 23
+      100  | 95   | 5
+      100  | 99   | 1
+      100  | 100  | 0
+      1000 | 971  | 2
+      8192 | 6144 | 25
+      5120 | 3840 | 25
+      5120 | 5118 | 0
+    end
+
+    with_them do
+      it 'returns the percentage of remaining storage rounding down to the nearest integer' do
+        set_storage_size_limit(namespace, megabytes: limit)
+        set_used_storage(namespace, megabytes: used)
+
+        expect(model.remaining_storage_percentage).to eq(expected_percentage)
+      end
+    end
+  end
+
+  describe '#remaining_storage_size' do
+    where(:limit, :used, :expected_size) do
+      0    | 0    | 0
+      0    | 100  | 0
+      100  | 0    | 100.megabytes
+      100  | 200  | 0
+      100  | 70   | 30.megabytes
+      100  | 85   | 15.megabytes
+      100  | 99   | 1.megabyte
+      100  | 100  | 0
+      1000 | 971  | 29.megabytes
+      8192 | 6144 | 2048.megabytes
+      5120 | 3840 | 1280.megabytes
+      5120 | 5118 | 2.megabytes
+    end
+
+    with_them do
+      it 'returns the remaining storage size in bytes' do
+        set_storage_size_limit(namespace, megabytes: limit)
+        set_used_storage(namespace, megabytes: used)
+
+        expect(model.remaining_storage_size).to eq(expected_size)
+      end
+    end
+  end
+
   describe '#enforce_limit?' do
     subject { model.enforce_limit? }
 
diff --git a/ee/spec/services/namespaces/storage/email_notification_service_spec.rb b/ee/spec/services/namespaces/storage/email_notification_service_spec.rb
index 0783c19d3071fa727ad263c62763067ff9ba4b60..88c4169222aab57eb01060c998a619f172f6cf6c 100644
--- a/ee/spec/services/namespaces/storage/email_notification_service_spec.rb
+++ b/ee/spec/services/namespaces/storage/email_notification_service_spec.rb
@@ -3,6 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Namespaces::Storage::EmailNotificationService do
+  include NamespaceStorageHelpers
   using RSpec::Parameterized::TableSyntax
 
   describe 'execute' do
@@ -224,14 +225,6 @@
     end
   end
 
-  def set_storage_size_limit(group, megabytes:)
-    group.gitlab_subscription.hosted_plan.actual_limits.update!(storage_size_limit: megabytes)
-  end
-
-  def set_used_storage(group, megabytes:)
-    group.root_storage_statistics.update!(storage_size: megabytes.megabytes)
-  end
-
   def set_notification_level(level)
     group.root_storage_statistics.update!(notification_level: level)
   end
diff --git a/ee/spec/support/helpers/namespace_storage_helpers.rb b/ee/spec/support/helpers/namespace_storage_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..94615cf748493ceb4933d25144b80068e0d5a5c3
--- /dev/null
+++ b/ee/spec/support/helpers/namespace_storage_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module NamespaceStorageHelpers
+  def set_storage_size_limit(namespace, megabytes:)
+    namespace.gitlab_subscription.hosted_plan.actual_limits.update!(storage_size_limit: megabytes)
+  end
+
+  def set_used_storage(namespace, megabytes:)
+    namespace.root_storage_statistics.update!(storage_size: megabytes.megabytes)
+  end
+end
diff --git a/ee/spec/workers/ee/namespaces/root_statistics_worker_spec.rb b/ee/spec/workers/ee/namespaces/root_statistics_worker_spec.rb
index e892555adc777246ea57043a239fc60c26c45c9c..f28632a7be2b350aea876084adcf73a2371b7aa5 100644
--- a/ee/spec/workers/ee/namespaces/root_statistics_worker_spec.rb
+++ b/ee/spec/workers/ee/namespaces/root_statistics_worker_spec.rb
@@ -3,6 +3,8 @@
 require 'spec_helper'
 
 RSpec.describe Namespaces::RootStatisticsWorker, '#perform', :saas do
+  include NamespaceStorageHelpers
+
   let_it_be(:group, refind: true) { create(:group_with_plan, :with_aggregation_schedule, plan: :ultimate_plan) }
   let_it_be(:project, refind: true) { create(:project, namespace: group) }
   let_it_be(:owner) { create(:user) }
@@ -87,8 +89,4 @@
       end
     end
   end
-
-  def set_storage_size_limit(group, megabytes:)
-    group.gitlab_subscription.hosted_plan.actual_limits.update!(storage_size_limit: megabytes)
-  end
 end