diff --git a/app/controllers/concerns/cycle_analytics_params.rb b/app/controllers/concerns/cycle_analytics_params.rb
index 2aaf8f2b45179b3a442b0f5a2fd5e7a5c3c8ccf6..91456561a17e1ae41a562b7b6ff0e9012f4b71e3 100644
--- a/app/controllers/concerns/cycle_analytics_params.rb
+++ b/app/controllers/concerns/cycle_analytics_params.rb
@@ -1,6 +1,10 @@
 module CycleAnalyticsParams
   extend ActiveSupport::Concern
 
+  def options
+    @options ||= { from: start_date(events_params), current_user: current_user }
+  end
+
   def start_date(params)
     params[:start_date] == '30' ? 30.days.ago : 90.days.ago
   end
diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index 13b3eec761fa52645d92aa1abd88fedccbf83659..5e9524b15db9e5c0bb75ec3cef2d792e94cec9dc 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -51,10 +51,6 @@ module Projects
         @events ||= Gitlab::CycleAnalytics::Events.new(project: project, options: options)
       end
     
-      def options
-        @options ||= { from: start_date(events_params), current_user: current_user }
-      end
-    
       def events_params
         return {} unless params[:events].present?
     
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index 73fe3c9c4c9279faeb372430bbc0b38c08d362c2..93dbe2819e74c72e1c09685c2651a97c4dee5554 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -6,7 +6,9 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
   before_action :authorize_read_cycle_analytics!
 
   def show
-    @cycle_analytics = ::CycleAnalytics.new(@project, current_user, from: start_date(cycle_analytics_params))
+    @cycle_analytics = ::CycleAnalytics.new(@project, options: options)
+
+    @cycle_analytics_no_data = @cycle_analytics.no_stats?
 
     respond_to do |format|
       format.html
@@ -25,8 +27,8 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
   def cycle_analytics_json
     {
       summary: @cycle_analytics.summary,
-      stats: nil, # TODO
-      permissions: @cycle_analytics.permissions(user: current_user)# TODO
+      stats: @cycle_analytics.stats,
+      permissions: @cycle_analytics.permissions(user: current_user)
     }
   end
 end
diff --git a/app/models/cycle_analytics.rb b/app/models/cycle_analytics.rb
index 9681d34f2d1d3bbc731aa532866951617b543c51..00e9f7c7d5cae42d07805e75fc6db8c5ad0817fb 100644
--- a/app/models/cycle_analytics.rb
+++ b/app/models/cycle_analytics.rb
@@ -1,7 +1,7 @@
 class CycleAnalytics
   STAGES = %i[issue plan code test review staging production].freeze
 
-  def initialize(project, from:)
+  def initialize(project, options:)
     @project = project
     @options = options
   end
@@ -10,22 +10,28 @@ class CycleAnalytics
     @summary ||= Gitlab::CycleAnalytics::Summary.new(@project, from: @options[:from]).data
   end
 
-  def method_missing(method_sym, *arguments, &block)
-    classify_stage(method_sym).new(project: @project, options: @options, stage: method_sym)
+  def stats
+    @stats ||= stats_per_stage
+  end
+
+  def no_stats?
+    stats.map(&:value).compact.empty?
   end
 
   def permissions(user:)
     Gitlab::CycleAnalytics::Permissions.get(user: user, project: @project)
   end
 
-  def issue
-    @fetcher.calculate_metric(:issue,
-                              Issue.arel_table[:created_at],
-                              [Issue::Metrics.arel_table[:first_associated_with_milestone_at],
-                               Issue::Metrics.arel_table[:first_added_to_board_at]])
+  private
+
+  def stats_per_stage
+    STAGES.map do |stage_name|
+      classify_stage(method_sym).new(project: @project, options: @options, stage: stage_name).median_data
+    end
   end
 
-  def classify_stage(method_sym)
-    "Gitlab::CycleAnalytics::#{method_sym.to_s.capitalize}Stage".constantize
+  def classify_stage(stage_name)
+    "Gitlab::CycleAnalytics::#{stage_name.to_s.capitalize}Stage".constantize
   end
+
 end
diff --git a/lib/gitlab/cycle_analytics/summary.rb b/lib/gitlab/cycle_analytics/summary.rb
index 7d172855a94c05b246fa8d83cb2834229085ffe0..5f0103c9d5a88990960bb71762be8e524f630856 100644
--- a/lib/gitlab/cycle_analytics/summary.rb
+++ b/lib/gitlab/cycle_analytics/summary.rb
@@ -9,9 +9,9 @@ module Gitlab
       end
 
       def data
-        [serialize(issue),
-         serialize(commit),
-         serialize(deploy)]
+        [serialize(Summary::Issue.new(project: @project, from: @from)),
+         serialize(Summary::Commit.new(project: @project, from: @from)),
+         serialize(Summary::Deploy.new(project: @project, from: @from))]
       end
 
       private
@@ -19,18 +19,6 @@ module Gitlab
       def serialize(summary_object)
         AnalyticsSummarySerializer.new.represent(summary_object).as_json
       end
-
-      def issue
-        Summary::Issue.new(project: @project, from: @from)
-      end
-
-      def deploy
-        Summary::Deploy.new(project: @project, from: @from)
-      end
-
-      def commit
-        Summary::Commit.new(project: @project, from: @from)
-      end
     end
   end
 end
diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb
index 7771785ead3e9182f2145765029a23f18068c455..4838b57e3533370b764a4783ceb151c4e6f240ad 100644
--- a/spec/models/cycle_analytics/code_spec.rb
+++ b/spec/models/cycle_analytics/code_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   context 'with deployment' do
     generate_cycle_analytics_spec(
@@ -16,10 +16,10 @@ describe 'CycleAnalytics#code', feature: true do
                                -> (context, data) do
                                  context.create_commit_referencing_issue(data[:issue])
                                end]],
-      end_time_conditions:   [["merge request that closes issue is created",
-                               -> (context, data) do
-                                 context.create_merge_request_closing_issue(data[:issue])
-                               end]],
+      end_time_conditions: [["merge request that closes issue is created",
+                             -> (context, data) do
+                               context.create_merge_request_closing_issue(data[:issue])
+                             end]],
       post_fn: -> (context, data) do
         context.merge_merge_requests_closing_issue(data[:issue])
         context.deploy_master
@@ -50,10 +50,10 @@ describe 'CycleAnalytics#code', feature: true do
                                -> (context, data) do
                                  context.create_commit_referencing_issue(data[:issue])
                                end]],
-      end_time_conditions:   [["merge request that closes issue is created",
-                               -> (context, data) do
-                                 context.create_merge_request_closing_issue(data[:issue])
-                               end]],
+      end_time_conditions: [["merge request that closes issue is created",
+                             -> (context, data) do
+                               context.create_merge_request_closing_issue(data[:issue])
+                             end]],
       post_fn: -> (context, data) do
         context.merge_merge_requests_closing_issue(data[:issue])
       end)
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
index 5ed3d37f2fbfb18601d2c271d88e1612a1f38d4e..ce6e99bbec9d9c571df90b534bafd8de59710322 100644
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ b/spec/models/cycle_analytics/issue_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :issue,
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index baf3e3241a128cfac97440ef60cf3ac27b84a029..bd5a6a77b7a3d32d05adc4331535bc850d7aa2cd 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :plan,
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
index 21b9c6e71507a7e93fcd63c192bcd2dc346ea938..653e203b491d07cffe785e4db7431dab9820a68e 100644
--- a/spec/models/cycle_analytics/production_spec.rb
+++ b/spec/models/cycle_analytics/production_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :production,
diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb
index 158621d59a43ef0edd38fca5e6230ea12cd554a5..219cd4c02122dc8fa1b2c9e7f43cafd48521e7a6 100644
--- a/spec/models/cycle_analytics/review_spec.rb
+++ b/spec/models/cycle_analytics/review_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :review,
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
index dad653964b74cd59b16aae8b5c8426ace1f2b34f..8dffb6b8fe150aeefbd7ade4363161b74e1d0781 100644
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ b/spec/models/cycle_analytics/staging_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :staging,
diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb
index 725bc68b25f457f1b9b9116d5d5b6e329756d393..1a54c57a27844cea3bbbbba38ef8290ee61fe608 100644
--- a/spec/models/cycle_analytics/summary_spec.rb
+++ b/spec/models/cycle_analytics/summary_spec.rb
@@ -4,7 +4,7 @@ describe CycleAnalytics::Summary, models: true do
   let(:project) { create(:project) }
   let(:from) { Time.now }
   let(:user) { create(:user, :admin) }
-  subject { described_class.new(project, user, from: from) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   describe "#new_issues" do
     it "finds the number of issues created after the 'from date'" do
diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb
index 2313724e8f38274aba2301bbb98b95d2dc46ab5c..ac1304beca8048226d818b319dde8b578545eee0 100644
--- a/spec/models/cycle_analytics/test_spec.rb
+++ b/spec/models/cycle_analytics/test_spec.rb
@@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do
   let(:project) { create(:project) }
   let(:from_date) { 10.days.ago }
   let(:user) { create(:user, :admin) }
-  subject { CycleAnalytics.new(project, user, from: from_date) }
+  subject { CycleAnalyticsTest.new(project, options: { from: from_date }) }
 
   generate_cycle_analytics_spec(
     phase: :test,
diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb
index 8e19a6c92e2e29c7d5b6b1adbe39760da44ddc2e..ab6241616168de78e7cc2ccddbb8552cde096585 100644
--- a/spec/support/cycle_analytics_helpers/test_generation.rb
+++ b/spec/support/cycle_analytics_helpers/test_generation.rb
@@ -1,8 +1,13 @@
+class CycleAnalyticsTest < CycleAnalytics
+  def method_missing(method_sym, *arguments, &block)
+    classify_stage(method_sym).new(project: @project, options: @options, stage: method_sym).median
+  end
+end
+
 # rubocop:disable Metrics/AbcSize
 
 # Note: The ABC size is large here because we have a method generating test cases with
 #       multiple nested contexts. This shouldn't count as a violation.
-
 module CycleAnalyticsHelpers
   module TestGeneration
     # Generate the most common set of specs that all cycle analytics phases need to have.