diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 773ebddba2b9c4758368a1d82ec267d72622c83a..21416f0fa02a29cbed228e9c4de238fe33f3039a 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -20,14 +20,16 @@ module Gitlab
     #
     # Returns an HTML-safe String
     def self.render(text, context = {})
-      pipeline = context[:pipeline] || :full
-
-      html_pipeline = html_pipelines[pipeline]
-
-      transformers = get_context_transformers(pipeline)
-      context = transformers.reduce(context) { |context, transformer| transformer.call(context) }
+      cache_key = context.delete(:cache_key)
 
-      html_pipeline.to_html(text, context)
+      if cache_key
+        cache_key = full_cache_key(cache_key, context[:pipeline])
+        Rails.cache.fetch(cache_key) do
+          cacheless_render(text, context)
+        end
+      else
+        cacheless_render(text, context)
+      end
     end
 
     # Provide autoload paths for filters to prevent a circular dependency error
@@ -130,9 +132,7 @@ module Gitlab
       ],
       email: [
         :full,
-        { 
-          only_path: false 
-        }
+        { only_path: false }
       ],
       description: [
         :full,
@@ -155,6 +155,17 @@ module Gitlab
       end
     end
 
+    def self.cacheless_render(text, context = {})
+      pipeline = context[:pipeline] || :full
+
+      html_pipeline = html_pipelines[pipeline]
+
+      transformers = get_context_transformers(pipeline)
+      context = transformers.reduce(context) { |context, transformer| transformer.call(context) }
+
+      html_pipeline.to_html(text, context)
+    end
+
     def self.get_filters(pipelines)
       Array.wrap(pipelines).flat_map do |pipeline|
         case pipeline
@@ -182,5 +193,9 @@ module Gitlab
         end
       end.compact
     end
+
+    def self.full_cache_key(cache_key, pipeline = :full)
+      ["markdown", *cache_key, pipeline]
+    end
   end
 end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 633c988d0255d3e2a38319db4be0b8693115841e..2262e5a168a57d0e5559d8addb0c53a401b2ab4b 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -11,10 +11,10 @@ module Gitlab
       @load_lazy_references = load_lazy_references
     end
 
-    def analyze(text)
+    def analyze(text, cache_key: nil)
       references.clear
 
-      @document = Gitlab::Markdown.render(text, project: project)
+      @document = Gitlab::Markdown.render(text, project: project, cache_key: cache_key)
     end
 
     %i(user label issue merge_request snippet commit commit_range).each do |type|