diff --git a/config/feature_flags/development/ci_rules_changes_compare.yml b/config/feature_flags/development/ci_rules_changes_compare.yml
deleted file mode 100644
index 094692def262e263e86ec876d810fc6b8b0c8c82..0000000000000000000000000000000000000000
--- a/config/feature_flags/development/ci_rules_changes_compare.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_rules_changes_compare
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90968
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366412
-milestone: '15.3'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 478818ad361822f08d28057c870d58aad233b5fa..6075a64653232034cb5ea32ba7458c2dee073ef2 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -3343,7 +3343,8 @@ In this example, both jobs have the same behavior.
 
 ##### `rules:changes:compare_to`
 
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293645) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `ci_rules_changes_compare`. Enabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293645) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `ci_rules_changes_compare`. Enabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/366412) in GitLab 15.5. Feature flag `ci_rules_changes_compare` removed.
 
 Use `rules:changes:compare_to` to specify which ref to compare against for changes to the files
 listed under [`rules:changes:paths`](#ruleschangespaths).
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 1034f5eacefc5dd7ebedf013528fc5fa5ad49890..4069a683ceb4d84158212c5edb8cdde3f515754a 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -41,7 +41,6 @@ def paths
 
         def find_modified_paths(pipeline)
           return unless pipeline
-          return pipeline.modified_paths unless ::Feature.enabled?(:ci_rules_changes_compare, pipeline.project)
 
           compare_to_sha = find_compare_to_sha(pipeline)
 
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index 234ba68d6278361793bc843562412fad8b61d261..a22aa30304b8eeab76800a899999e200df81a576 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
@@ -122,19 +122,17 @@
       context 'when compare_to is branch or tag' do
         using RSpec::Parameterized::TableSyntax
 
-        where(:pipeline_ref, :compare_to, :paths, :ff, :result) do
-          'feature_1' | 'master'    | ['file1.txt'] | true  | true
-          'feature_1' | 'master'    | ['README.md'] | true  | false
-          'feature_1' | 'master'    | ['xyz.md']    | true  | false
-          'feature_2' | 'master'    | ['file1.txt'] | true  | true
-          'feature_2' | 'master'    | ['file2.txt'] | true  | true
-          'feature_2' | 'feature_1' | ['file1.txt'] | true  | false
-          'feature_2' | 'feature_1' | ['file1.txt'] | false | true
-          'feature_2' | 'feature_1' | ['file2.txt'] | true  | true
-          'feature_1' | 'tag_1'     | ['file1.txt'] | true  | false
-          'feature_1' | 'tag_1'     | ['file1.txt'] | false | true
-          'feature_1' | 'tag_1'     | ['file2.txt'] | true  | true
-          'feature_2' | 'tag_1'     | ['file2.txt'] | true  | true
+        where(:pipeline_ref, :compare_to, :paths, :result) do
+          'feature_1' | 'master'    | ['file1.txt'] | true
+          'feature_1' | 'master'    | ['README.md'] | false
+          'feature_1' | 'master'    | ['xyz.md']    | false
+          'feature_2' | 'master'    | ['file1.txt'] | true
+          'feature_2' | 'master'    | ['file2.txt'] | true
+          'feature_2' | 'feature_1' | ['file1.txt'] | false
+          'feature_2' | 'feature_1' | ['file2.txt'] | true
+          'feature_1' | 'tag_1'     | ['file1.txt'] | false
+          'feature_1' | 'tag_1'     | ['file2.txt'] | true
+          'feature_2' | 'tag_1'     | ['file2.txt'] | true
         end
 
         with_them do
@@ -144,10 +142,6 @@
             build(:ci_pipeline, project: project, ref: pipeline_ref, sha: project.commit(pipeline_ref).sha)
           end
 
-          before do
-            stub_feature_flags(ci_rules_changes_compare: ff)
-          end
-
           it { is_expected.to eq(result) }
         end
       end
@@ -174,14 +168,6 @@
             ::Gitlab::Ci::Build::Rules::Rule::Clause::ParseError, 'rules:changes:compare_to is not a valid ref'
           )
         end
-
-        context 'when the FF ci_rules_changes_compare is disabled' do
-          before do
-            stub_feature_flags(ci_rules_changes_compare: false)
-          end
-
-          it { is_expected.to be_truthy }
-        end
       end
     end
   end
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index fc57ca66d3a69ff986c5c09f549ca46e3b1b2acf..87e9b4400e78fdc3fea211a25493c84cbe765ed3 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -544,16 +544,6 @@ def find_job(name)
                 'Failed to parse rule for job1: rules:changes:compare_to is not a valid ref'
               ])
             end
-
-            context 'when the FF ci_rules_changes_compare is not enabled' do
-              before do
-                stub_feature_flags(ci_rules_changes_compare: false)
-              end
-
-              it 'ignores compare_to and changes is always true' do
-                expect(build_names).to contain_exactly('job1', 'job2')
-              end
-            end
           end
 
           context 'when the compare_to ref exists' do
@@ -563,16 +553,6 @@ def find_job(name)
               it 'creates job1 and job2' do
                 expect(build_names).to contain_exactly('job1', 'job2')
               end
-
-              context 'when the FF ci_rules_changes_compare is not enabled' do
-                before do
-                  stub_feature_flags(ci_rules_changes_compare: false)
-                end
-
-                it 'ignores compare_to and changes is always true' do
-                  expect(build_names).to contain_exactly('job1', 'job2')
-                end
-              end
             end
 
             context 'when the rule does not match' do
@@ -581,16 +561,6 @@ def find_job(name)
               it 'does not create job1' do
                 expect(build_names).to contain_exactly('job2')
               end
-
-              context 'when the FF ci_rules_changes_compare is not enabled' do
-                before do
-                  stub_feature_flags(ci_rules_changes_compare: false)
-                end
-
-                it 'ignores compare_to and changes is always true' do
-                  expect(build_names).to contain_exactly('job1', 'job2')
-                end
-              end
             end
           end
         end
@@ -616,17 +586,6 @@ def find_job(name)
               expect(pipeline).to be_created_successfully
               expect(build_names).to contain_exactly('job1')
             end
-
-            context 'when the FF ci_rules_changes_compare is not enabled' do
-              before do
-                stub_feature_flags(ci_rules_changes_compare: false)
-              end
-
-              it 'ignores compare_to and changes is always true' do
-                expect(pipeline).to be_created_successfully
-                expect(build_names).to contain_exactly('job1')
-              end
-            end
           end
 
           context 'when the rule does not match' do