diff --git a/ee/app/models/ee/group.rb b/ee/app/models/ee/group.rb
index c9b4705a0e346d113021779b555f74fa31026b2e..1b792c7869f3cee27df09e78a99c7cbd63617c90 100644
--- a/ee/app/models/ee/group.rb
+++ b/ee/app/models/ee/group.rb
@@ -546,10 +546,14 @@ def block_seat_overages?
         ::Gitlab::Saas.feature_available?(:gitlab_com_subscriptions)
     end
 
-    def seats_available_for?(invites)
+    def seats_available_for?(user_ids)
       return true unless gitlab_subscription
 
-      gitlab_subscription.seats >= (billable_members_count + invites.count)
+      billable_ids = billed_user_ids[:user_ids].to_a
+
+      new_user_ids = user_ids - billable_ids
+
+      gitlab_subscription.seats >= (billable_ids.count + new_user_ids.count)
     end
 
     def calculate_reactive_cache
diff --git a/ee/app/services/ee/members/create_service.rb b/ee/app/services/ee/members/create_service.rb
index 4245fd3f9d63314d5ca7f993bcaf423d6a27bc55..719b075734259c6f22b098fd8bcbbae8cd623d30 100644
--- a/ee/app/services/ee/members/create_service.rb
+++ b/ee/app/services/ee/members/create_service.rb
@@ -52,7 +52,12 @@ def check_membership_lock!
       def check_seats!
         root_namespace = source.root_ancestor
 
-        return unless root_namespace.block_seat_overages? && !root_namespace.seats_available_for?(invites)
+        return unless root_namespace.block_seat_overages?
+
+        # Work in progress. Handle email invites in https://gitlab.com/gitlab-org/gitlab/-/issues/443383.
+        invited_user_ids = invites.select { |i| i.to_i.to_s == i }
+
+        return if root_namespace.seats_available_for?(invited_user_ids.map(&:to_i))
 
         raise ::Members::CreateService::SeatLimitExceededError, s_('AddMember|Not enough seats for this many users.')
       end
diff --git a/ee/spec/models/ee/group_spec.rb b/ee/spec/models/ee/group_spec.rb
index 6f762db449b459e40529349e1d0da383ef2f6fb0..195030940f84bc0ff4fdc40f000e9ae0cad2a55b 100644
--- a/ee/spec/models/ee/group_spec.rb
+++ b/ee/spec/models/ee/group_spec.rb
@@ -3626,6 +3626,7 @@ def webhook_headers
   describe '#seats_available_for?' do
     context 'with a subscription', :saas do
       let_it_be(:group, refind: true) { create(:group_with_plan, plan: :premium_plan) }
+      let_it_be(:user) { create(:user) }
 
       before_all do
         group.gitlab_subscription.update!(seats: 5)
@@ -3651,19 +3652,26 @@ def webhook_headers
 
       it 'counts members in subgroups as consuming seats' do
         subgroup = create(:group, parent: group)
-        subgroup.add_developer(create(:user))
+        subgroup.add_developer(user)
         user_ids = [1, 2, 3, 4, 5]
 
         expect(group.seats_available_for?(user_ids)).to eq(false)
       end
 
-      it 'returns true if passed an empty enumerable' do
+      it 'considers if users are already consuming a seat' do
+        group.gitlab_subscription.update!(seats: 1)
+        group.add_developer(user)
+
+        expect(group.seats_available_for?([user.id])).to eq(true)
+      end
+
+      it 'returns true if passed an empty array' do
         expect(group.seats_available_for?([])).to eq(true)
       end
 
-      it 'returns true if there are no seats remaining and the passed enumerable is empty' do
+      it 'returns true if there are no seats remaining and the passed array is empty' do
         group.gitlab_subscription.update!(seats: 1)
-        group.add_maintainer(create(:user))
+        group.add_maintainer(user)
 
         expect(group.seats_available_for?([])).to eq(true)
       end
diff --git a/ee/spec/requests/api/invitations_spec.rb b/ee/spec/requests/api/invitations_spec.rb
index 7f7f08880ec18e0355e1108b94d0c6a85e3bfdde..afde90da659737bcd359f62c9fb93d43cfcea2f6 100644
--- a/ee/spec/requests/api/invitations_spec.rb
+++ b/ee/spec/requests/api/invitations_spec.rb
@@ -371,6 +371,17 @@
         })
       end
 
+      it 'adds the member when the member is already in the group when all the seats are taken' do
+        group.gitlab_subscription.update!(seats: 2)
+        group.add_guest(user)
+
+        post api(url, owner), params: { access_level: Member::DEVELOPER, user_id: user.id }
+
+        expect(project.members.flat_map { |m| [m.user_id, m.access_level] }).to eq([user.id, Member::DEVELOPER])
+        expect(response).to have_gitlab_http_status(:created)
+        expect(json_response).to eq({ 'status' => 'success' })
+      end
+
       context 'when the feature flag is disabled' do
         before do
           stub_feature_flags(block_seat_overages: false)
diff --git a/ee/spec/services/ee/members/create_service_spec.rb b/ee/spec/services/ee/members/create_service_spec.rb
index f21e3bd48c0af31d9b04795ccbfdd78e9ea11a96..42566fc6c383e86d781a8ca45c69fb2b6392b138 100644
--- a/ee/spec/services/ee/members/create_service_spec.rb
+++ b/ee/spec/services/ee/members/create_service_spec.rb
@@ -299,4 +299,29 @@
       end
     end
   end
+
+  context 'with block seat overages enabled', :saas do
+    let_it_be(:user) { create(:user) }
+    let_it_be(:group) { create(:group_with_plan, plan: :premium_plan) }
+    let_it_be(:project) { create(:project, group: group) }
+
+    before_all do
+      project.add_maintainer(user)
+    end
+
+    before do
+      stub_saas_features(gitlab_com_subscriptions: true)
+      stub_feature_flags(block_seat_overages: true)
+    end
+
+    context 'with invited emails' do
+      let(:invites) { ['email@example.com'] }
+
+      it 'removes invite emails from the seat check' do
+        group.gitlab_subscription.update!(seats: 1)
+
+        expect { execute_service }.to change { project.members.count }.by(1)
+      end
+    end
+  end
 end