diff --git a/ee/config/feature_flags/experiment/ai_tracking_data_gathering.yml b/ee/config/feature_flags/experiment/ai_tracking_data_gathering.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4cf88435b6477f7edbf09803a93e573325411b36
--- /dev/null
+++ b/ee/config/feature_flags/experiment/ai_tracking_data_gathering.yml
@@ -0,0 +1,9 @@
+---
+name: ai_tracking_data_gathering
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/441485
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146918
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/454106
+milestone: '16.11'
+group: group::optimize
+type: experiment
+default_enabled: false
diff --git a/ee/lib/api/code_suggestions.rb b/ee/lib/api/code_suggestions.rb
index b424bdb3d973394f2b07974a6cb55a3f5e4afa56..b1e09d1f1f254b2a483d8be27ca3d51d7501dc46 100644
--- a/ee/lib/api/code_suggestions.rb
+++ b/ee/lib/api/code_suggestions.rb
@@ -96,6 +96,7 @@ def saas_headers
             'code_suggestions_requested',
             user: current_user
           )
+          Gitlab::Tracking::AiTracking.track_event('code_suggestions_requested', user_id: current_user.id)
 
           workhorse_headers =
             Gitlab::Workhorse.send_url(
diff --git a/ee/lib/gitlab/tracking/ai_tracking.rb b/ee/lib/gitlab/tracking/ai_tracking.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8659461b65c457a37c0749f1ecfd2698740205ac
--- /dev/null
+++ b/ee/lib/gitlab/tracking/ai_tracking.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Tracking
+    module AiTracking
+      EVENTS = {
+        'code_suggestions_requested' => 1
+      }.freeze
+
+      class << self
+        def track_event(event_name, context_hash = {})
+          return unless Feature.enabled?(:ai_tracking_data_gathering)
+
+          ::ClickHouse::WriteBuffer.write_event(context_hash.merge(event: EVENTS[event_name], timestamp: Time.zone.now))
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/lib/gitlab/tracking/ai_tracking_spec.rb b/ee/spec/lib/gitlab/tracking/ai_tracking_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..db75244c33a52149add73b32f7f594ef98bc05a0
--- /dev/null
+++ b/ee/spec/lib/gitlab/tracking/ai_tracking_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::AiTracking, feature_category: :value_stream_management do
+  describe '.track_event', :freeze_time do
+    subject(:track_event) { described_class.track_event(event_name, event_context) }
+
+    let(:event_context) { { user_id: 1, language: 'ruby' } }
+    let(:event_name) { 'code_suggestions_requested' }
+
+    it 'writes to ClickHouse buffer with event data' do
+      expect(::ClickHouse::WriteBuffer)
+        .to receive(:write_event).with(event_context.merge(event: 1, timestamp: Time.zone.now)).once
+
+      track_event
+    end
+
+    context 'when :ai_tracking_data_gathering feature flag is disabled' do
+      before do
+        stub_feature_flags(ai_tracking_data_gathering: false)
+      end
+
+      it 'does not write to ClickHouse buffer' do
+        expect(::ClickHouse::WriteBuffer).not_to receive(:write_event)
+
+        track_event
+      end
+    end
+  end
+end
diff --git a/ee/spec/requests/api/code_suggestions_spec.rb b/ee/spec/requests/api/code_suggestions_spec.rb
index 0526ab5cf0bea4d1a1923c281211467530da01ad..5b1f5135bf48f897de2e52158451fa74c0050141 100644
--- a/ee/spec/requests/api/code_suggestions_spec.rb
+++ b/ee/spec/requests/api/code_suggestions_spec.rb
@@ -30,6 +30,7 @@
                                         .and_return(false)
 
     allow(Gitlab::InternalEvents).to receive(:track_event)
+    allow(Gitlab::Tracking::AiTracking).to receive(:track_event)
   end
 
   shared_examples 'a response' do |case_name|
@@ -239,6 +240,14 @@ def request
           )
         end
 
+        it 'tracks code_suggestions_requested ai event' do
+          post_api
+
+          expect(Gitlab::Tracking::AiTracking)
+            .to have_received(:track_event)
+                  .with('code_suggestions_requested', user_id: current_user.id)
+        end
+
         context 'with telemetry headers' do
           let(:headers) do
             {
@@ -394,8 +403,8 @@ def request
             let(:current_user) { authorized_user }
             let(:prefix) do
               <<~PREFIX
-              def is_even(n: int) ->
-              # A function that outputs the first 20 fibonacci numbers
+                def is_even(n: int) ->
+                # A function that outputs the first 20 fibonacci numbers
               PREFIX
             end
 
@@ -550,8 +559,8 @@ def get_user(session):
             let(:current_user) { authorized_user }
             let(:prefix) do
               <<~PREFIX
-              def is_even(n: int) ->
-              # A function that outputs the first 20 fibonacci numbers
+                def is_even(n: int) ->
+                # A function that outputs the first 20 fibonacci numbers
               PREFIX
             end
 
diff --git a/lib/click_house/write_buffer.rb b/lib/click_house/write_buffer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..691363d5509aa5f9db93f73da075af0560adfc3b
--- /dev/null
+++ b/lib/click_house/write_buffer.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module ClickHouse
+  module WriteBuffer
+    BUFFER_KEY = 'clickhouse_write_buffer'
+
+    class << self
+      def write_event(event_hash)
+        Gitlab::Redis::SharedState.with do |redis|
+          redis.lpush(BUFFER_KEY, event_hash.to_json)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/lib/click_house/write_buffer_spec.rb b/spec/lib/click_house/write_buffer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..31a6f9caedc981f0c9a13ff9108d1f1e6f4b2bed
--- /dev/null
+++ b/spec/lib/click_house/write_buffer_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ClickHouse::WriteBuffer, :clean_gitlab_redis_shared_state, feature_category: :database do
+  describe '.write_event' do
+    subject(:write_event) { described_class.write_event(event_hash) }
+
+    let(:event_hash) { { foo: 'bar' } }
+
+    it 'saves ClickHouse event to Redis' do
+      expect do
+        write_event
+      end.to change {
+        Gitlab::Redis::SharedState.with do |redis|
+          redis.lrange(described_class::BUFFER_KEY, 0, 10)
+        end
+      }.from([]).to([event_hash.to_json])
+    end
+  end
+end