diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 97e6e9471e0a7167adb82c0d864639a1df8157a3..40a23a6f806aa94c09ac879f597a7ccfeb7b6d7c 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -10,8 +10,7 @@ class Projects::ServicesController < Projects::ApplicationController
   layout "project_settings"
 
   def index
-    @project.build_missing_services
-    @services = @project.services.visible.reload
+    @services = @project.find_or_initialize_services
   end
 
   def edit
@@ -46,6 +45,6 @@ class Projects::ServicesController < Projects::ApplicationController
   private
 
   def service
-    @service ||= @project.services.find { |service| service.to_param == params[:id] }
+    @service ||= @project.find_or_initialize_service(params[:id])
   end
 end
diff --git a/app/models/project.rb b/app/models/project.rb
index 327f81412f830eebbf0c11248e454199542e219a..4aedc91dc34f1e94ecfd8f390944ea776daade95 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -77,7 +77,6 @@ class Project < ActiveRecord::Base
   has_many :boards, before_add: :validate_board_limit, dependent: :destroy
 
   # Project services
-  has_many :services
   has_one :campfire_service, dependent: :destroy
   has_one :drone_ci_service, dependent: :destroy
   has_one :emails_on_push_service, dependent: :destroy
@@ -749,27 +748,32 @@ class Project < ActiveRecord::Base
     update_column(:has_external_wiki, services.external_wikis.any?)
   end
 
-  def build_missing_services
+  def find_or_initialize_services
     services_templates = Service.where(template: true)
 
-    Service.available_services_names.each do |service_name|
+    Service.available_services_names.map do |service_name|
       service = find_service(services, service_name)
 
-      # If service is available but missing in db
-      if service.nil?
+      if service
+        service
+      else
         # We should check if template for the service exists
         template = find_service(services_templates, service_name)
 
         if template.nil?
-          # If no template, we should create an instance. Ex `create_gitlab_ci_service`
-          public_send("create_#{service_name}_service")
+          # If no template, we should create an instance. Ex `build_gitlab_ci_service`
+          public_send("build_#{service_name}_service")
         else
-          Service.create_from_template(self.id, template)
+          Service.build_from_template(id, template)
         end
       end
     end
   end
 
+  def find_or_initialize_service(name)
+    find_or_initialize_services.find { |service| service.to_param == name }
+  end
+
   def create_labels
     Label.templates.each do |label|
       params = label.attributes.except('id', 'template', 'created_at', 'updated_at')
diff --git a/app/models/service.rb b/app/models/service.rb
index 625fbc483029c000890adb1dec5ce9f6fa8ddb00..9d6ff190cdf739e04cb6ed4a54286d12fc7da55f 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -222,11 +222,11 @@ class Service < ActiveRecord::Base
     ]
   end
 
-  def self.create_from_template(project_id, template)
+  def self.build_from_template(project_id, template)
     service = template.dup
     service.template = false
     service.project_id = project_id
-    service if service.save
+    service
   end
 
   private
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 15d7918e7fd18f71e5251112421ab69aa66b90f6..28db145a1f40ae8e49237db1c79845cdfad2d3a7 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -95,7 +95,7 @@ module Projects
 
       unless @project.gitlab_project_import?
         @project.create_wiki unless skip_wiki?
-        @project.build_missing_services
+        create_services_from_active_templates(@project)
 
         @project.create_labels
       end
@@ -135,5 +135,12 @@ module Projects
 
       @project
     end
+
+    def create_services_from_active_templates(project)
+      Service.where(template: true, active: true).each do |template|
+        service = Service.build_from_template(project.id, template)
+        service.save!
+      end
+    end
   end
 end
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index 4a33a5bc6f6b8a67d59504a854c2f60c8a83c1b9..66fd3029dc9ae73db20a2f8d57e8d54c9b2b1c96 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -28,5 +28,6 @@
           %td.hidden-xs
             = service.description
           %td.light
-            = time_ago_in_words service.updated_at
-            ago
+            - if service.updated_at.present?
+              = time_ago_in_words service.updated_at
+              ago
diff --git a/changelogs/unreleased/adam-build-missing-services-when-necessary.yml b/changelogs/unreleased/adam-build-missing-services-when-necessary.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8b157e31e99d31f7b43d3febae40f239bb68ba41
--- /dev/null
+++ b/changelogs/unreleased/adam-build-missing-services-when-necessary.yml
@@ -0,0 +1,4 @@
+---
+title: Defer saving project services to the database if there are no user changes
+merge_request: 6958
+author:
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 6998b6dc039cd855323862eb35bb0b2be9611da1..84cc9200d1bd1b5816ff6349856f047a03801ce4 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -86,25 +86,10 @@ module API
     end
 
     def project_service
-      @project_service ||= begin
-        underscored_service = params[:service_slug].underscore
-
-        if Service.available_services_names.include?(underscored_service)
-          user_project.build_missing_services
-
-          service_method = "#{underscored_service}_service"
-
-          send_service(service_method)
-        end
-      end
-
+      @project_service ||= user_project.find_or_initialize_service(params[:service_slug].underscore)
       @project_service || not_found!("Service")
     end
 
-    def send_service(service_method)
-      user_project.send(service_method)
-    end
-
     def service_attributes
       @service_attributes ||= project_service.fields.inject([]) do |arr, hash|
         arr << hash[:name].to_sym
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3a0c3ec21cdb2433b0304a3720ffc1e14d4b77d1..c74d9c282cfe920e42a18bd3a534d977b1a87cfc 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -496,9 +496,6 @@ describe Project, models: true do
     end
 
     it 'returns nil and does not query services when there is no external issue tracker' do
-      project.build_missing_services
-      project.reload
-
       expect(project).not_to receive(:services)
 
       expect(project.external_issue_tracker).to eq(nil)
@@ -506,9 +503,6 @@ describe Project, models: true do
 
     it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
       ext_project.reload # Factory returns a project with changed attributes
-      ext_project.build_missing_services
-      ext_project.reload
-
       expect(ext_project).to receive(:services).once.and_call_original
 
       2.times { expect(ext_project.external_issue_tracker).to be_a_kind_of(RedmineService) }
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 43937a54b2cf53225d8c925789403a77ad247146..b1615a95004cc6b21355dd7214565844b3eea0eb 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -53,7 +53,7 @@ describe Service, models: true do
 
   describe "Template" do
     describe "for pushover service" do
-      let(:service_template) do
+      let!(:service_template) do
         PushoverService.create(
           template: true,
           properties: {
@@ -66,13 +66,9 @@ describe Service, models: true do
       let(:project) { create(:project) }
 
       describe 'is prefilled for projects pushover service' do
-        before do
-          service_template
-          project.build_missing_services
-        end
-
         it "has all fields prefilled" do
-          service = project.pushover_service
+          service = project.find_or_initialize_service('pushover')
+
           expect(service.template).to eq(false)
           expect(service.device).to eq('MyDevice')
           expect(service.sound).to eq('mic')
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 375671bca4c27b5e47c97195c751c62a1bc5ca15..2aadab3cbe11ae74042a3014ed4bc7693ca53789 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -56,8 +56,7 @@ describe API::API, api: true  do
 
       # inject some properties into the service
       before do
-        project.build_missing_services
-        service_object = project.send(service_method)
+        service_object = project.find_or_initialize_service(service)
         service_object.properties = service_attrs
         service_object.save
       end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 876bfaf085c77a3235460de6f298010a7e316321..2cf9883113cc9e0761e93068a7bd30cf5e100d6d 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -10,13 +10,6 @@ describe Projects::CreateService, services: true do
       }
     end
 
-    it 'creates services on Project creation' do
-      project = create_project(@user, @opts)
-      project.reload
-
-      expect(project.services).not_to be_empty
-    end
-
     it 'creates labels on Project creation if there are templates' do
       Label.create(title: "bug", template: true)
       project = create_project(@user, @opts)
@@ -137,6 +130,19 @@ describe Projects::CreateService, services: true do
         expect(project.namespace).to eq(@user.namespace)
       end
     end
+
+    context 'when there is an active service template' do
+      before do
+        create(:service, project: nil, template: true, active: true)
+      end
+
+      it 'creates a service from this template' do
+        project = create_project(@user, @opts)
+        project.reload
+
+        expect(project.services.count).to eq 1
+      end
+    end
   end
 
   def create_project(user, opts)