diff --git a/lib/search.rb b/lib/search.rb
index fe19f17937e..16b813d8587 100644
--- a/lib/search.rb
+++ b/lib/search.rb
@@ -1164,6 +1164,10 @@ class Search
     query.includes(topic: topic_eager_loads)
   end
 
+  # Limited for performance reasons since `TS_HEADLINE` is slow when the text
+  # document is too long.
+  MAX_LENGTH_FOR_HEADLINE = 2500
+
   def posts_scope(default_scope = Post.all)
     if SiteSetting.use_pg_headlines_for_excerpt
       search_term = @term.present? ? PG::Connection.escape_string(@term) : nil
@@ -1174,7 +1178,7 @@ class Search
         .joins("INNER JOIN topics t1 ON t1.id = posts.topic_id")
         .select(
           "TS_HEADLINE(#{ts_config}, t1.fancy_title, PLAINTO_TSQUERY(#{ts_config}, '#{search_term}'), 'StartSel=''<span class=\"#{HIGHLIGHT_CSS_CLASS}\">'', StopSel=''</span>''') AS topic_title_headline",
-          "TS_HEADLINE(#{ts_config}, pd.raw_data, PLAINTO_TSQUERY(#{ts_config}, '#{search_term}'), 'ShortWord=0, MaxFragments=1, MinWords=50, MaxWords=51, StartSel=''<span class=\"#{HIGHLIGHT_CSS_CLASS}\">'', StopSel=''</span>''') AS headline",
+          "TS_HEADLINE(#{ts_config}, LEFT(pd.raw_data, #{MAX_LENGTH_FOR_HEADLINE}), PLAINTO_TSQUERY(#{ts_config}, '#{search_term}'), 'ShortWord=0, MaxFragments=1, MinWords=50, MaxWords=51, StartSel=''<span class=\"#{HIGHLIGHT_CSS_CLASS}\">'', StopSel=''</span>''') AS headline",
           default_scope.arel.projections
         )
     else
diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb
index 85c0183b8f2..2588bc27e09 100644
--- a/spec/components/search_spec.rb
+++ b/spec/components/search_spec.rb
@@ -429,6 +429,20 @@ describe Search do
       expect(post.topic_title_headline).to eq(topic.fancy_title)
     end
 
+    it "it limits the headline to #{Search::MAX_LENGTH_FOR_HEADLINE} characters" do
+      SiteSetting.use_pg_headlines_for_excerpt = true
+
+      reply.update!(raw: "#{'a' * Search::MAX_LENGTH_FOR_HEADLINE} #{reply.raw}")
+
+      result = Search.execute('elephant')
+
+      expect(result.posts.map(&:id)).to contain_exactly(reply.id)
+
+      post = result.posts.first
+
+      expect(post.headline.include?('elephant')).to eq(false)
+    end
+
     it 'returns the right post and blurb for searches with phrase' do
       SiteSetting.use_pg_headlines_for_excerpt = true