diff --git a/app/models/release.rb b/app/models/release.rb
index ecfae554fe00fe6f30b9ac0692e768d098fc935f..2543717895fde87e760732904ce88a91d0b1007d 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -34,7 +34,6 @@ class Release < ApplicationRecord
 
   delegate :repository, to: :project
 
-  after_commit :create_evidence!, on: :create, unless: :importing?
   after_commit :notify_new_release, on: :create, unless: :importing?
 
   MAX_NUMBER_TO_DISPLAY = 3
@@ -70,6 +69,10 @@ def upcoming_release?
     released_at.present? && released_at > Time.zone.now
   end
 
+  def historical_release?
+    released_at.present? && released_at < created_at
+  end
+
   def name
     self.read_attribute(:name) || tag
   end
@@ -98,10 +101,6 @@ def actual_tag
     end
   end
 
-  def create_evidence!
-    CreateEvidenceWorker.perform_async(self.id)
-  end
-
   def notify_new_release
     NewReleaseWorker.perform_async(id)
   end
diff --git a/changelogs/unreleased/38103-collect-release-evidence-at-moment-of-release-end-date.yml b/changelogs/unreleased/38103-collect-release-evidence-at-moment-of-release-end-date.yml
new file mode 100644
index 0000000000000000000000000000000000000000..97a5807ab17dc74f497157278ff5546a8c4e9b41
--- /dev/null
+++ b/changelogs/unreleased/38103-collect-release-evidence-at-moment-of-release-end-date.yml
@@ -0,0 +1,5 @@
+---
+title: Collect release evidence at release timestamp
+merge_request: 23697
+author:
+type: added
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 506d2b0f9859dff638fa2e737b2800f13acd46b2..b1f23d9837f0564fc5c9d5f60be178dee2feb5ba 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -67,6 +67,7 @@ class Releases < Grape::API
 
         if result[:status] == :success
           log_release_created_audit_event(result[:release])
+          create_evidence!
 
           present result[:release], with: Entities::Release, current_user: current_user
         else
@@ -164,6 +165,16 @@ def log_release_updated_audit_event
       def log_release_milestones_updated_audit_event
         # This is a separate method so that EE can extend its behaviour
       end
+
+      def create_evidence!
+        return if release.historical_release?
+
+        if release.upcoming_release?
+          CreateEvidenceWorker.perform_at(release.released_at, release.id)
+        else
+          CreateEvidenceWorker.perform_async(release.id)
+        end
+      end
     end
   end
 end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 2f84b92b806b63f9c20facb7f161bf3b0ef81c22..85e398c7d5ff80177d28ae94b5013234efcf91c4 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -53,12 +53,6 @@
     end
   end
 
-  describe 'callbacks' do
-    it 'creates a new Evidence object on after_commit', :sidekiq_inline do
-      expect { release }.to change(Evidence, :count).by(1)
-    end
-  end
-
   describe '#assets_count' do
     subject { release.assets_count }
 
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index ae95b54a5902cd36e328cc36fcff31d428864c23..e0f88caeab663e51868866e3b5eab38a62c55558 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -9,6 +9,7 @@
   let(:guest) { create(:user) }
   let(:non_project_member) { create(:user) }
   let(:commit) { create(:commit, project: project) }
+  let(:last_release) { project.releases.last }
 
   before do
     project.add_maintainer(maintainer)
@@ -709,6 +710,109 @@
         expect(response).to have_gitlab_http_status(:conflict)
       end
     end
+
+    context 'Evidence collection' do
+      let(:params) do
+        {
+          name: 'New release',
+          tag_name: 'v0.1',
+          description: 'Super nice release',
+          released_at: released_at
+        }.compact
+      end
+
+      around do |example|
+        Timecop.freeze { example.run }
+      end
+
+      subject do
+        post api("/projects/#{project.id}/releases", maintainer), params: params
+      end
+
+      context 'historical release' do
+        let(:released_at) { 3.weeks.ago }
+
+        it 'does not execute CreateEvidenceWorker' do
+          expect { subject }.not_to change(CreateEvidenceWorker.jobs, :size)
+        end
+
+        it 'does not create an Evidence object', :sidekiq_inline do
+          expect { subject }.not_to change(Evidence, :count)
+        end
+
+        it 'is a historical release' do
+          subject
+
+          expect(last_release.historical_release?).to be_truthy
+        end
+
+        it 'is not an upcoming release' do
+          subject
+
+          expect(last_release.upcoming_release?).to be_falsy
+        end
+      end
+
+      context 'immediate release' do
+        let(:released_at) { nil }
+
+        it 'sets `released_at` to the current dttm' do
+          subject
+
+          expect(last_release.updated_at).to be_like_time(Time.now)
+        end
+
+        it 'queues CreateEvidenceWorker' do
+          expect { subject }.to change(CreateEvidenceWorker.jobs, :size).by(1)
+        end
+
+        it 'creates Evidence', :sidekiq_inline do
+          expect { subject }.to change(Evidence, :count).by(1)
+        end
+
+        it 'is not a historical release' do
+          subject
+
+          expect(last_release.historical_release?).to be_falsy
+        end
+
+        it 'is not an upcoming release' do
+          subject
+
+          expect(last_release.upcoming_release?).to be_falsy
+        end
+      end
+
+      context 'upcoming release' do
+        let(:released_at) { 1.day.from_now }
+
+        it 'queues CreateEvidenceWorker' do
+          expect { subject }.to change(CreateEvidenceWorker.jobs, :size).by(1)
+        end
+
+        it 'queues CreateEvidenceWorker at the released_at timestamp' do
+          subject
+
+          expect(CreateEvidenceWorker.jobs.last['at']).to eq(released_at.to_i)
+        end
+
+        it 'creates Evidence', :sidekiq_inline do
+          expect { subject }.to change(Evidence, :count).by(1)
+        end
+
+        it 'is not a historical release' do
+          subject
+
+          expect(last_release.historical_release?).to be_falsy
+        end
+
+        it 'is an upcoming release' do
+          subject
+
+          expect(last_release.upcoming_release?).to be_truthy
+        end
+      end
+    end
   end
 
   describe 'PUT /projects/:id/releases/:tag_name' do