diff --git a/CHANGELOG b/CHANGELOG
index 14f2f14becd441a82cfe26058dd7d6ffb17fe559..051bc033117694c065d455c8ca73d5f486366e6b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -26,6 +26,7 @@ v 8.4.2
     track them in Performance Monitoring.
   - Increase contrast between highlighted code comments and inline diff marker
   - Fix method undefined when using external commit status in builds
+  - Optimized performance of finding issues to be closed by a merge request (Yorick Peterse)
 
 v 8.4.1
   - Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3),
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 41dd248d80a2ad8def8d55336d5145f0415a85f8..09af60a2016ee667d478a6b346f60738d465d0ea 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -346,10 +346,10 @@ class MergeRequest < ActiveRecord::Base
   # Return the set of issues that will be closed if this merge request is accepted.
   def closes_issues(current_user = self.author)
     if target_branch == project.default_branch
-      issues = commits.flat_map { |c| c.closes_issues(current_user) }
-      issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).
-                  closed_by_message(description))
-      issues.uniq(&:id)
+      messages = commits.map(&:safe_message) << description
+
+      Gitlab::ClosingIssueExtractor.new(project, current_user).
+        closed_by_message(messages.join("\n"))
     else
       []
     end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 291e6200a5bcd1ff6f6080cdaff97bcbac059b9b..46f2f20b98667c74c1d0ed554101330123cf7c49 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -137,9 +137,10 @@ describe MergeRequest, models: true do
   describe 'detection of issues to be closed' do
     let(:issue0) { create :issue, project: subject.project }
     let(:issue1) { create :issue, project: subject.project }
-    let(:commit0) { double('commit0', closes_issues: [issue0]) }
-    let(:commit1) { double('commit1', closes_issues: [issue0]) }
-    let(:commit2) { double('commit2', closes_issues: [issue1]) }
+
+    let(:commit0) { double('commit0', safe_message: "Fixes #{issue0.to_reference}") }
+    let(:commit1) { double('commit1', safe_message: "Fixes #{issue0.to_reference}") }
+    let(:commit2) { double('commit2', safe_message: "Fixes #{issue1.to_reference}") }
 
     before do
       allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
@@ -149,7 +150,9 @@ describe MergeRequest, models: true do
       allow(subject.project).to receive(:default_branch).
         and_return(subject.target_branch)
 
-      expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id))
+      closed = subject.closes_issues
+
+      expect(closed).to include(issue0, issue1)
     end
 
     it 'only lists issues as to be closed if it targets the default branch' do
@@ -167,17 +170,6 @@ describe MergeRequest, models: true do
 
       expect(subject.closes_issues).to include(issue2)
     end
-
-    context 'for a project with JIRA integration' do
-      let(:issue0) { JiraIssue.new('JIRA-123', subject.project) }
-      let(:issue1) { JiraIssue.new('FOOBAR-4567', subject.project) }
-
-      it 'returns sorted JiraIssues' do
-        allow(subject.project).to receive_messages(default_branch: subject.target_branch)
-
-        expect(subject.closes_issues).to eq([issue0, issue1])
-      end
-    end
   end
 
   describe "#work_in_progress?" do