diff --git a/doc/development/service_ping/metrics_instrumentation.md b/doc/development/service_ping/metrics_instrumentation.md
index 3d56f3e777fcbef0e6ad3da331c84e1e0fef5acf..42f93d6ae24e6dc61a4aa2f6e51c40c8c5587f7f 100644
--- a/doc/development/service_ping/metrics_instrumentation.md
+++ b/doc/development/service_ping/metrics_instrumentation.md
@@ -40,6 +40,7 @@ We have built a domain-specific language (DSL) to define the metrics instrumenta
 - `start`: Specifies the start value of the batch counting, by default is `relation.minimum(:id)`.
 - `finish`: Specifies the end value of the batch counting, by default is `relation.maximum(:id)`.
 - `cache_start_and_finish_as`: Specifies the cache key for `start` and `finish` values and sets up caching them. Use this call when `start` and `finish` are expensive queries that should be reused between different metric calculations.
+- `available?`: Specifies whether the metric should be reported. The default is `true`.
 
 [Example of a merge request that adds a database metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60022).
 
@@ -123,6 +124,37 @@ options:
   counter_class: SourceCodeCounter
 ```
 
+### Availability-restrained Redis metrics
+
+If the Redis metric should only be available in the report under some conditions, then you must specify these conditions in a new class that is a child of the `RedisMetric` class.
+
+```ruby
+# frozen_string_literal: true
+
+module Gitlab
+  module Usage
+    module Metrics
+      module Instrumentations
+        class MergeUsageCountRedisMetric < RedisMetric
+          available? { Feature.enabled?(:merge_usage_data_missing_key_paths) }
+        end
+      end
+    end
+  end
+end
+```
+
+You must also use the class's name in the YAML setup.
+
+```yaml
+time_frame: all
+data_source: redis
+instrumentation_class: 'MergeUsageCountRedisMetric'
+options:
+  event: pushes
+  counter_class: SourceCodeCounter
+```
+
 ## Redis HyperLogLog metrics
 
 [Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685).
@@ -138,8 +170,42 @@ options:
     - i_quickactions_approve
 ```
 
+### Availability-restrained Redis HyperLogLog metrics
+
+If the Redis HyperLogLog metric should only be available in the report under some conditions, then you must specify these conditions in a new class that is a child of the `RedisHLLMetric` class.
+
+```ruby
+# frozen_string_literal: true
+
+module Gitlab
+  module Usage
+    module Metrics
+      module Instrumentations
+        class MergeUsageCountRedisHLLMetric < RedisHLLMetric
+          available? { Feature.enabled?(:merge_usage_data_missing_key_paths) }
+        end
+      end
+    end
+  end
+end
+```
+
+You must also use the class's name in the YAML setup.
+
+```yaml
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: 'MergeUsageCountRedisHLLMetric'
+options:
+  events:
+    - i_quickactions_approve
+```
+
 ## Generic metrics
 
+- `value`: Specifies the value of the metric.
+- `available?`: Specifies whether the metric should be reported. The default is `true`.
+
 [Example of a merge request that adds a generic metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60256).
 
 ```ruby
diff --git a/ee/spec/config/metrics/every_metric_definition_spec.rb b/ee/spec/config/metrics/every_metric_definition_spec.rb
index dcffdbcbe2ceda39a4ae2776955482ea3d9b3646..655781d668f96bb55aa9c75bd2672545189925dd 100644
--- a/ee/spec/config/metrics/every_metric_definition_spec.rb
+++ b/ee/spec/config/metrics/every_metric_definition_spec.rb
@@ -104,6 +104,7 @@ def assert_uses_all_nested_classes(parent_module)
         if constant.is_a? Class
           metric_class_instance = instance_double(constant)
           expect(constant).to receive(:new).at_least(:once).and_return(metric_class_instance)
+          allow(metric_class_instance).to receive(:available?).and_return(true)
           expect(metric_class_instance).to receive(:value).at_least(:once)
         elsif constant.is_a? Module
           assert_uses_all_nested_classes(constant)
diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb
index 24e044c57400244215b511fae107745e64cb8b3a..cf48aa49938c3603952fe4b85cba4f8e546c286d 100644
--- a/lib/gitlab/usage/metric.rb
+++ b/lib/gitlab/usage/metric.rb
@@ -18,19 +18,25 @@ def all
       end
 
       def with_value
-        unflatten_key_path(intrumentation_object.value)
+        with_availability(proc { instrumentation_object.value })
       end
 
       def with_instrumentation
-        unflatten_key_path(intrumentation_object.instrumentation)
+        with_availability(proc { instrumentation_object.instrumentation })
       end
 
       def with_suggested_name
-        unflatten_key_path(intrumentation_object.suggested_name)
+        with_availability(proc { instrumentation_object.suggested_name })
       end
 
       private
 
+      def with_availability(value_proc)
+        return {} unless instrumentation_object.available?
+
+        unflatten_key_path(value_proc.call)
+      end
+
       def unflatten_key_path(value)
         ::Gitlab::Usage::Metrics::KeyPathProcessor.process(definition.key_path, value)
       end
@@ -39,8 +45,8 @@ def instrumentation_class
         "Gitlab::Usage::Metrics::Instrumentations::#{definition.instrumentation_class}"
       end
 
-      def intrumentation_object
-        instrumentation_class.constantize.new(
+      def instrumentation_object
+        @instrumentation_object ||= instrumentation_class.constantize.new(
           time_frame: definition.time_frame,
           options: definition.attributes[:options]
         )
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index a264f9484f3a8fec6a8e3e6099a9a72513875df0..f76ed1753b28f48fd0b691ccb9f17f9557479ff7 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -11,6 +11,18 @@ class BaseMetric
           attr_reader :time_frame
           attr_reader :options
 
+          class << self
+            def available?(&block)
+              return @metric_available = block if block_given?
+
+              return @metric_available.call if instance_variable_defined?('@metric_available')
+
+              true
+            end
+
+            attr_reader :metric_available
+          end
+
           def initialize(time_frame:, options: {})
             @time_frame = time_frame
             @options = options
@@ -19,6 +31,10 @@ def initialize(time_frame:, options: {})
           def instrumentation
             value
           end
+
+          def available?
+            self.class.available?
+          end
         end
       end
     end
diff --git a/spec/lib/gitlab/usage/metric_spec.rb b/spec/lib/gitlab/usage/metric_spec.rb
index 19d2d3048eb7b2cfb9e54dfddd88a3569a4e9d04..10ae94e746b4360e12cb414a07b3140272af13dc 100644
--- a/spec/lib/gitlab/usage/metric_spec.rb
+++ b/spec/lib/gitlab/usage/metric_spec.rb
@@ -51,4 +51,31 @@
       expect(described_class.new(issue_count_metric_definiton).with_suggested_name).to eq({ counts: { issues: 'count_issues' } })
     end
   end
+
+  context 'unavailable metric' do
+    let(:instrumentation_class) { "UnavailableMetric" }
+    let(:issue_count_metric_definiton) do
+      double(:issue_count_metric_definiton,
+        attributes.merge({ attributes: attributes, instrumentation_class: instrumentation_class })
+      )
+    end
+
+    before do
+      unavailable_metric_class = Class.new(Gitlab::Usage::Metrics::Instrumentations::CountIssuesMetric) do
+        def available?
+          false
+        end
+      end
+
+      stub_const("Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}", unavailable_metric_class)
+    end
+
+    [:with_value, :with_instrumentation, :with_suggested_name].each do |method_name|
+      describe "##{method_name}" do
+        it 'returns an empty hash' do
+          expect(described_class.new(issue_count_metric_definiton).public_send(method_name)).to eq({})
+        end
+      end
+    end
+  end
 end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
index ea5ae1970dedf9dbfd96d95607adfcf18b58f3a6..cd7eb44c83d6c9c4ea5742f65c25281f01e46806 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
@@ -71,6 +71,33 @@
       end
     end
 
+    context 'with availability defined' do
+      subject do
+        described_class.tap do |metric_class|
+          metric_class.relation { Issue }
+          metric_class.operation :count
+          metric_class.available? { false }
+        end.new(time_frame: 'all')
+      end
+
+      it 'responds to #available? properly' do
+        expect(subject.available?).to eq(false)
+      end
+    end
+
+    context 'with availability not defined' do
+      subject do
+        Class.new(described_class) do
+          relation { Issue }
+          operation :count
+        end.new(time_frame: 'all')
+      end
+
+      it 'responds to #available? properly' do
+        expect(subject.available?).to eq(true)
+      end
+    end
+
     context 'with cache_start_and_finish_as called' do
       subject do
         described_class.tap do |metric_class|
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb
index 347a2c779cb2a76ddb7ea2e9db3b435113c87b38..9730605153326506c520967a06bb20aef8bf00ee 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb
@@ -25,4 +25,28 @@
   it 'raise exception if events options is not present' do
     expect { described_class.new(time_frame: '28d') }.to raise_error(ArgumentError)
   end
+
+  describe 'children classes' do
+    let(:options) { { events: ['i_quickactions_approve'] } }
+
+    context 'availability not defined' do
+      subject { Class.new(described_class).new(time_frame: nil, options: options) }
+
+      it 'returns default availability' do
+        expect(subject.available?).to eq(true)
+      end
+    end
+
+    context 'availability defined' do
+      subject do
+        Class.new(described_class) do
+          available? { false }
+        end.new(time_frame: nil, options: options)
+      end
+
+      it 'returns defined availability' do
+        expect(subject.available?).to eq(false)
+      end
+    end
+  end
 end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
index fb3bd1ba8341dfa0b6adf4dc4b6390cc41d7e33e..831f775ec9aaa90b746fd14f1b923dad4dba4b6b 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
@@ -20,4 +20,28 @@
   it 'raises an exception if counter_class option is not present' do
     expect { described_class.new(event: 'pushes') }.to raise_error(ArgumentError)
   end
+
+  describe 'children classes' do
+    let(:options) { { event: 'pushes', counter_class: 'SourceCodeCounter' } }
+
+    context 'availability not defined' do
+      subject { Class.new(described_class).new(time_frame: nil, options: options) }
+
+      it 'returns default availability' do
+        expect(subject.available?).to eq(true)
+      end
+    end
+
+    context 'availability defined' do
+      subject do
+        Class.new(described_class) do
+          available? { false }
+        end.new(time_frame: nil, options: options)
+      end
+
+      it 'returns defined availability' do
+        expect(subject.available?).to eq(false)
+      end
+    end
+  end
 end