diff --git a/bin/feature-flag b/bin/feature-flag
index b5e7889be1d7bc85f7ff40a1765e4bfd26bba1dd..43e273be1fa914dc255565366b74540155fce191 100755
--- a/bin/feature-flag
+++ b/bin/feature-flag
@@ -126,6 +126,8 @@ class FeatureFlagOptionParser
       $stdout.puts ">> Specify the feature flag type:"
       $stdout.puts
       TYPES.each do |type, data|
+        next if data[:deprecated]
+
         $stdout.puts "#{type.to_s.rjust(15)}#{' '*6}#{data[:description]}"
       end
 
@@ -133,7 +135,7 @@ class FeatureFlagOptionParser
         $stdout.print "?> "
 
         type = $stdin.gets.strip.to_sym
-        return type if TYPES[type]
+        return type if TYPES[type] && !TYPES[type][:deprecated]
 
         $stderr.puts "Invalid type specified '#{type}'"
       end
diff --git a/config/initializers/0_inject_feature_flags.rb b/config/initializers/0_inject_feature_flags.rb
index 5b33b3bb4eab555d181e35b9caf30df25003c3a3..1e0c3c01abae7b3b9118a3db95a24a8a746172e7 100644
--- a/config/initializers/0_inject_feature_flags.rb
+++ b/config/initializers/0_inject_feature_flags.rb
@@ -4,3 +4,49 @@
 Feature.register_feature_groups
 Feature.register_definitions
 Feature.register_hot_reloader unless Rails.configuration.cache_classes
+
+# This disallows usage of licensed feature names with the same name
+# as feature flags. This naming collision creates confusion and it was
+# decided to be removed in favor of explicit check.
+# https://gitlab.com/gitlab-org/gitlab/-/issues/259611
+if Gitlab.ee? && Gitlab.dev_or_test_env?
+  # These are the names of feature flags that do violate the constraint of
+  # being unique to licensed names. These feature flags should be reworked to
+  # be "development" with explicit check
+  IGNORED_FEATURE_FLAGS = %i[
+    resource_access_token
+    ci_secrets_management
+    feature_flags_related_issues
+    group_coverage_reports
+    group_wikis
+    incident_sla
+    swimlanes
+    minimal_access_role
+  ].to_set
+
+  # First, we validate a list of overrides to ensure that these overrides
+  # are removed if feature flag is gone
+  missing_feature_flags = IGNORED_FEATURE_FLAGS.reject do |feature_flag|
+    Feature::Definition.definitions[feature_flag]
+  end
+
+  if missing_feature_flags.any?
+    raise "The following feature flags were added as an override for discovering licensed features. " \
+          "Since these feature flags seems to be gone, ensure to remove them from \`IGNORED_FEATURE_FLAGS\` " \
+          "in \`#{__FILE__}'`: #{missing_feature_flags.join(", ")}"
+  end
+
+  # Second, we validate that there's no feature flag under the name as licensed feature
+  # flag, to ensure that the name used, is unique
+  licensed_features = License::PLANS_BY_FEATURE.keys.select do |licensed_feature_name|
+    IGNORED_FEATURE_FLAGS.exclude?(licensed_feature_name) &&
+      Feature::Definition.definitions[licensed_feature_name]
+  end
+
+  if licensed_features.any?
+    raise "The following feature flags do use a licensed feature. " \
+          "To avoid the confusion between their usage it is disallowed to use feature flag " \
+          "with exact the same name as licensed feature name. Use a different name to create " \
+          "a distinction: #{licensed_features.join(", ")}"
+  end
+end
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index e6668b0fd038dc5a87e0356472a7c881bb5f99ec..6c672663baed4e74586c180b27e8b181fc35bd4c 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -61,30 +61,6 @@ Feature.disabled?(:my_ops_flag, project, type: :ops)
 push_frontend_feature_flag(:my_ops_flag, project, type: :ops)
 ```
 
-### `licensed` type
-
-`licensed` feature flags are used to temporarily disable licensed features. There
-should be a one-to-one mapping of `licensed` feature flags to licensed features.
-
-`licensed` feature flags must be `default_enabled: true`, because that's the only
-supported option in the current implementation. This is under development as per
-the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
-
-The `licensed` type has a dedicated set of functions to check if a licensed
-feature is available for a project or namespace. This check validates
-if the license is assigned to the namespace and feature flag itself.
-The `licensed` feature flag has the same name as a licensed feature name:
-
-```ruby
-# Good: checks if feature flag is enabled
-project.feature_available?(:my_licensed_feature)
-namespace.feature_available?(:my_licensed_feature)
-
-# Bad: licensed flag must be accessed via `feature_available?`
-Feature.enabled?(:my_licensed_feature, type: :licensed)
-push_frontend_feature_flag(:my_licensed_feature, type: :licensed)
-```
-
 ## Feature flag definition and validation
 
 > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3.
@@ -309,25 +285,16 @@ used as an actor for `Feature.enabled?`.
 
 ### Feature flags for licensed features
 
-The [`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68),
-[`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) (EE), and
-[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) (EE) methods all implicitly check for
-a by default enabled feature flag with the same name as the provided argument.
-
-**An important side-effect of the implicit feature flags mentioned above is that
-unless the feature is explicitly disabled or limited to a percentage of users,
-the feature flag check defaults to `true`.**
-
-NOTE: **Note:**
-Due to limitations with `feature_available?`, the YAML definition for `licensed` feature
-flags accepts only `default_enabled: true`. This is under development as per the
-[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
+You can't use a feature flag with the same name as a licensed feature name, because
+it would cause a naming collision. This was [widely discussed and removed](https://gitlab.com/gitlab-org/gitlab/-/issues/259611)
+because it is confusing.
 
-If you want a licensed feature to be disabled by default or enabled only for a given gate, you can use a feature flag with a different name. The feature checks would then
-look like:
+To check for licensed features, add a dedicated feature flag under a different name
+and check it explicitly, for example:
 
 ```ruby
-Feature.enabled?(:licensed_feature_feature_flag, project) && project.feature_available?(:licensed_feature)
+Feature.enabled?(:licensed_feature_feature_flag, project) &&
+  project.feature_available?(:licensed_feature)
 ```
 
 ### Feature groups
diff --git a/ee/lib/ee/api/features.rb b/ee/lib/ee/api/features.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a7d2cf644adb7f8923f7e39d15703d0826fcc15d
--- /dev/null
+++ b/ee/lib/ee/api/features.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module EE
+  module API
+    module Features
+      extend ActiveSupport::Concern
+
+      prepended do
+        helpers do
+          extend ::Gitlab::Utils::Override
+
+          override :validate_licensed_name!
+          def validate_feature_flag_name!(name)
+            super
+
+            if License::PLANS_BY_FEATURE[name.to_sym]
+              bad_request!(
+                "The '#{name}' is a licensed feature name, " \
+                "and thus it cannot be used as a feature flag name. " \
+                "Use `rails console` to set this feature flag state."
+              )
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/requests/api/features_spec.rb b/ee/spec/requests/api/features_spec.rb
index ed9ef598cb31ef162050805d038ac9de3bb388c5..920abc8e4b70c6fb295163ae322133166049f43d 100644
--- a/ee/spec/requests/api/features_spec.rb
+++ b/ee/spec/requests/api/features_spec.rb
@@ -32,6 +32,18 @@
         end.to change(Geo::CacheInvalidationEvent, :count).by(1)
       end
     end
+
+    context 'when licensed feature name is given' do
+      let(:feature_name) do
+        License::PLANS_BY_FEATURE.each_key.first
+      end
+
+      it 'returns bad request' do
+        post api("/features/#{feature_name}", admin), params: { value: 'true' }
+
+        expect(response).to have_gitlab_http_status(:bad_request)
+      end
+    end
   end
 
   describe 'DELETE /feature/:name' do
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 5d2e545abd623594c2c0d546c8bf26f7a375f540..70feef12cebd1880a7ed416e7feb5ca360d7fe6b 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -61,6 +61,8 @@ def gate_specified?(params)
         mutually_exclusive :key, :project
       end
       post ':name' do
+        validate_feature_flag_name!(params[:name])
+
         feature = Feature.get(params[:name]) # rubocop:disable Gitlab/AvoidFeatureGet
         targets = gate_targets(params)
         value = gate_value(params)
@@ -97,5 +99,13 @@ def gate_specified?(params)
         no_content!
       end
     end
+
+    helpers do
+      def validate_feature_flag_name!(name)
+        # no-op
+      end
+    end
   end
 end
+
+API::Features.prepend_if_ee('EE::API::Features')
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index 9ec56ee6b52508315b2b679acd960c9e2ceb6b16..5716bc007a60bac4817f1194dfb8b301af81216a 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -10,6 +10,8 @@ module Shared
     # rollout_issue: defines if `bin/feature-flag` asks for rollout issue
     # default_enabled: defines a default state of a feature flag when created by `bin/feature-flag`
     # ee_only: defines that a feature flag can only be created in a context of EE
+    # deprecated: defines if a feature flag type that is deprecated and to be removed,
+    #             the deprecated types are hidden from all interfaces
     # example: usage being shown when exception is raised
     TYPES = {
       development: {
@@ -37,6 +39,7 @@ module Shared
       },
       licensed: {
         description: 'Permanent feature flags used to temporarily disable licensed features.',
+        deprecated: true,
         optional: true,
         rollout_issue: false,
         ee_only: true,
diff --git a/spec/bin/feature_flag_spec.rb b/spec/bin/feature_flag_spec.rb
index 185a03fc587953d6c69024eb264e8a989d5525fa..8e0bed5b769053a6621bb6898c767a2723b9b7ca 100644
--- a/spec/bin/feature_flag_spec.rb
+++ b/spec/bin/feature_flag_spec.rb
@@ -123,6 +123,29 @@
         end
       end
 
+      context 'when there is deprecated feature flag type' do
+        before do
+          stub_const('FeatureFlagOptionParser::TYPES',
+            development: { description: 'short' },
+            deprecated: { description: 'deprecated', deprecated: true }
+          )
+        end
+
+        context 'and deprecated type is given' do
+          let(:type) { 'deprecated' }
+
+          it 'shows error message and retries' do
+            expect($stdin).to receive(:gets).and_return(type)
+            expect($stdin).to receive(:gets).and_raise('EOF')
+
+            expect do
+              expect { described_class.read_type }.to raise_error(/EOF/)
+            end.to output(/Specify the feature flag type/).to_stdout
+              .and output(/Invalid type specified/).to_stderr
+          end
+        end
+      end
+
       context 'when there are many types defined' do
         before do
           stub_const('FeatureFlagOptionParser::TYPES',