diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index ad7e0b23ff4103247b9879c2945d3d2cb8876808..49dec770096ee422c5e3b5eab8de5479bb5e97e6 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -164,11 +164,6 @@ module Ci
       builds.latest.with_artifacts_not_expired.includes(project: [:namespace])
     end
 
-    # For now the only user who participates is the user who triggered
-    def participants(_current_user = nil)
-      Array(user)
-    end
-
     def valid_commit_sha
       if self.sha == Gitlab::Git::BLANK_SHA
         self.errors.add(:sha, " cant be 00000000 (branch removal)")
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 52577bd52ea3043c1dd40b9a0578dac72223757b..e4726e62e935846018c4f1cc488481dacad92c5f 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -60,16 +60,25 @@ class NotificationSetting < ActiveRecord::Base
   def set_events
     return if custom?
 
-    EMAIL_EVENTS.each do |event|
-      events[event] = false
-    end
+    self.events = {}
   end
 
   # Validates store accessors values as boolean
   # It is a text field so it does not cast correct boolean values in JSON
   def events_to_boolean
     EMAIL_EVENTS.each do |event|
-      events[event] = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(events[event])
+      bool = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(public_send(event))
+
+      events[event] = bool
     end
   end
+
+  # Allow people to receive failed pipeline notifications if they already have
+  # custom notifications enabled, as these are more like mentions than the other
+  # custom settings.
+  def failed_pipeline
+    bool = super
+
+    bool.nil? || bool
+  end
 end
diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb
index 940e850600f8ab803a6d3cf90bbf3d8eb59ff75f..8bb995158de7e5baf8de86b5ffff098d5067c70d 100644
--- a/app/services/notification_recipient_service.rb
+++ b/app/services/notification_recipient_service.rb
@@ -3,7 +3,7 @@
 #
 class NotificationRecipientService
   attr_reader :project
-  
+
   def initialize(project)
     @project = project
   end
@@ -12,11 +12,7 @@ class NotificationRecipientService
     custom_action = build_custom_key(action, target)
 
     recipients = target.participants(current_user)
-
-    unless NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action)
-      recipients = add_project_watchers(recipients)
-    end
-
+    recipients = add_project_watchers(recipients)
     recipients = add_custom_notifications(recipients, custom_action)
     recipients = reject_mention_users(recipients)
 
@@ -43,6 +39,28 @@ class NotificationRecipientService
     recipients.uniq
   end
 
+  def build_pipeline_recipients(target, current_user, action:)
+    return [] unless current_user
+
+    custom_action =
+      case action.to_s
+      when 'failed'
+        :failed_pipeline
+      when 'success'
+        :success_pipeline
+      end
+
+    notification_setting = notification_setting_for_user_project(current_user, target.project)
+
+    return [] if notification_setting.mention? || notification_setting.disabled?
+
+    return [] if notification_setting.custom? && !notification_setting.public_send(custom_action)
+
+    return [] if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action)
+
+    reject_users_without_access([current_user], target)
+  end
+
   def build_relabeled_recipients(target, current_user, labels:)
     recipients = add_labels_subscribers([], target, labels: labels)
     recipients = reject_unsubscribed_users(recipients, target)
@@ -290,4 +308,16 @@ class NotificationRecipientService
   def build_custom_key(action, object)
     "#{action}_#{object.class.model_name.name.underscore}".to_sym
   end
+
+  def notification_setting_for_user_project(user, project)
+    project_setting = user.notification_settings_for(project)
+
+    return project_setting unless project_setting.global?
+
+    group_setting = user.notification_settings_for(project.group)
+
+    return group_setting unless group_setting.global?
+
+    user.global_notification_setting
+  end
 end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 2c6f849259e418543f84503a79400b6e2c15a66d..6b186263bd103c106c572837ef707779e31811ac 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -278,11 +278,11 @@ class NotificationService
 
     return unless mailer.respond_to?(email_template)
 
-    recipients ||= NotificationRecipientService.new(pipeline.project).build_recipients(
+    recipients ||= NotificationRecipientService.new(pipeline.project).build_pipeline_recipients(
       pipeline,
       pipeline.user,
       action: pipeline.status,
-      skip_current_user: false).map(&:notification_email)
+    ).map(&:notification_email)
 
     if recipients.any?
       mailer.public_send(email_template, pipeline, recipients).deliver_later
diff --git a/app/views/shared/notifications/_custom_notifications.html.haml b/app/views/shared/notifications/_custom_notifications.html.haml
index a736bfd91e2876d44a88b55b363ea5dbba5d2da8..708adbc38f13054263807cdb3ef0e49a1fc8c949 100644
--- a/app/views/shared/notifications/_custom_notifications.html.haml
+++ b/app/views/shared/notifications/_custom_notifications.html.haml
@@ -25,7 +25,7 @@
                   .form-group
                     .checkbox{ class: ("prepend-top-0" if index == 0) }
                       %label{ for: field_id }
-                        = check_box("notification_setting", event, id: field_id, class: "js-custom-notification-event", checked: notification_setting.events[event])
+                        = check_box("notification_setting", event, id: field_id, class: "js-custom-notification-event", checked: notification_setting.public_send(event))
                         %strong
                           = notification_event_name(event)
                           = icon("spinner spin", class: "custom-notification-event-loading")
diff --git a/changelogs/unreleased/quiet-pipelines.yml b/changelogs/unreleased/quiet-pipelines.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c02eb59b82472bd6693869f00d1e191d7d3cba87
--- /dev/null
+++ b/changelogs/unreleased/quiet-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Only email pipeline creators; only email for successful pipelines with custom
+  settings
+merge_request:
+author:
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index 4c52974e1038447b3de0f725b9e33b2c247fe765..e91d36987a93efc00e5c645a7cc653668b265a05 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -66,14 +66,13 @@ Below is the table of events users can be notified of:
 In all of the below cases, the notification will be sent to:
 - Participants:
   - the author and assignee of the issue/merge request
-  - the author of the pipeline
   - authors of comments on the issue/merge request
   - anyone mentioned by `@username` in the issue/merge request title or description
   - anyone mentioned by `@username` in any of the comments on the issue/merge request
 
     ...with notification level "Participating" or higher
 
-- Watchers: users with notification level "Watch" (however successful pipeline would be off for watchers)
+- Watchers: users with notification level "Watch"
 - Subscribers: anyone who manually subscribed to the issue/merge request
 - Custom: Users with notification level "custom" who turned on notifications for any of the events present in the table below
 
@@ -89,8 +88,8 @@ In all of the below cases, the notification will be sent to:
 | Reopen merge request   | |
 | Merge merge request    | |
 | New comment            | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
-| Failed pipeline        | The above, plus the author of the pipeline |
-| Successful pipeline    | The above, plus the author of the pipeline |
+| Failed pipeline        | The author of the pipeline |
+| Successful pipeline    | The author of the pipeline, if they have the custom notification setting for successful pipelines set |
 
 
 In addition, if the title or description of an Issue or Merge Request is
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index b67c96bc00d0bf5fccbd12e29720c738663471f1..561fbc8e247a53655f62ea62ebd141033ee79664 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -48,6 +48,10 @@ FactoryGirl.define do
       trait :success do
         status :success
       end
+
+      trait :failed do
+        status :failed
+      end
     end
   end
 end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 53282b999dc604e45f17b00992017b47cf62256d..e4a24fd63c22555e3fc84ab545e1bdf0b77be551 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1055,10 +1055,13 @@ describe Ci::Pipeline, models: true do
     end
 
     before do
-      reset_delivered_emails!
-
       project.team << [pipeline.user, Gitlab::Access::DEVELOPER]
 
+      pipeline.user.global_notification_setting.
+        update(level: 'custom', failed_pipeline: true, success_pipeline: true)
+
+      reset_delivered_emails!
+
       perform_enqueued_jobs do
         pipeline.enqueue
         pipeline.run
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 5c841843b40639b8b4f9a21c6ae48610bbd119cd..e3146a56495c5ad545906d3be25ceef40c0a2562 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -113,7 +113,7 @@ describe NotificationService, services: true do
         project.add_master(issue.assignee)
         project.add_master(note.author)
         create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@subscribed_participant cc this guy')
-        update_custom_notification(:new_note, @u_guest_custom, project)
+        update_custom_notification(:new_note, @u_guest_custom, resource: project)
         update_custom_notification(:new_note, @u_custom_global)
       end
 
@@ -379,7 +379,7 @@ describe NotificationService, services: true do
         build_team(note.project)
         reset_delivered_emails!
         allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
-        update_custom_notification(:new_note, @u_guest_custom, project)
+        update_custom_notification(:new_note, @u_guest_custom, resource: project)
         update_custom_notification(:new_note, @u_custom_global)
       end
 
@@ -457,7 +457,7 @@ describe NotificationService, services: true do
 
       add_users_with_subscription(issue.project, issue)
       reset_delivered_emails!
-      update_custom_notification(:new_issue, @u_guest_custom, project)
+      update_custom_notification(:new_issue, @u_guest_custom, resource: project)
       update_custom_notification(:new_issue, @u_custom_global)
     end
 
@@ -567,7 +567,7 @@ describe NotificationService, services: true do
 
     describe '#reassigned_issue' do
       before do
-        update_custom_notification(:reassign_issue, @u_guest_custom, project)
+        update_custom_notification(:reassign_issue, @u_guest_custom, resource: project)
         update_custom_notification(:reassign_issue, @u_custom_global)
       end
 
@@ -760,7 +760,7 @@ describe NotificationService, services: true do
 
     describe '#close_issue' do
       before do
-        update_custom_notification(:close_issue, @u_guest_custom, project)
+        update_custom_notification(:close_issue, @u_guest_custom, resource: project)
         update_custom_notification(:close_issue, @u_custom_global)
       end
 
@@ -791,7 +791,7 @@ describe NotificationService, services: true do
 
     describe '#reopen_issue' do
       before do
-        update_custom_notification(:reopen_issue, @u_guest_custom, project)
+        update_custom_notification(:reopen_issue, @u_guest_custom, resource: project)
         update_custom_notification(:reopen_issue, @u_custom_global)
       end
 
@@ -856,14 +856,14 @@ describe NotificationService, services: true do
     before do
       build_team(merge_request.target_project)
       add_users_with_subscription(merge_request.target_project, merge_request)
-      update_custom_notification(:new_merge_request, @u_guest_custom, project)
+      update_custom_notification(:new_merge_request, @u_guest_custom, resource: project)
       update_custom_notification(:new_merge_request, @u_custom_global)
       reset_delivered_emails!
     end
 
     describe '#new_merge_request' do
       before do
-        update_custom_notification(:new_merge_request, @u_guest_custom, project)
+        update_custom_notification(:new_merge_request, @u_guest_custom, resource: project)
         update_custom_notification(:new_merge_request, @u_custom_global)
       end
 
@@ -952,7 +952,7 @@ describe NotificationService, services: true do
 
     describe '#reassigned_merge_request' do
       before do
-        update_custom_notification(:reassign_merge_request, @u_guest_custom, project)
+        update_custom_notification(:reassign_merge_request, @u_guest_custom, resource: project)
         update_custom_notification(:reassign_merge_request, @u_custom_global)
       end
 
@@ -1026,7 +1026,7 @@ describe NotificationService, services: true do
 
     describe '#closed_merge_request' do
       before do
-        update_custom_notification(:close_merge_request, @u_guest_custom, project)
+        update_custom_notification(:close_merge_request, @u_guest_custom, resource: project)
         update_custom_notification(:close_merge_request, @u_custom_global)
       end
 
@@ -1056,7 +1056,7 @@ describe NotificationService, services: true do
 
     describe '#merged_merge_request' do
       before do
-        update_custom_notification(:merge_merge_request, @u_guest_custom, project)
+        update_custom_notification(:merge_merge_request, @u_guest_custom, resource: project)
         update_custom_notification(:merge_merge_request, @u_custom_global)
       end
 
@@ -1108,7 +1108,7 @@ describe NotificationService, services: true do
 
     describe '#reopen_merge_request' do
       before do
-        update_custom_notification(:reopen_merge_request, @u_guest_custom, project)
+        update_custom_notification(:reopen_merge_request, @u_guest_custom, resource: project)
         update_custom_notification(:reopen_merge_request, @u_custom_global)
       end
 
@@ -1281,40 +1281,172 @@ describe NotificationService, services: true do
   describe 'Pipelines' do
     describe '#pipeline_finished' do
       let(:project) { create(:project, :public, :repository) }
-      let(:current_user) { create(:user) }
       let(:u_member) { create(:user) }
-      let(:u_other) { create(:user) }
+      let(:u_watcher) { create_user_with_notification(:watch, 'watcher') }
+
+      let(:u_custom_notification_unset) do
+        create_user_with_notification(:custom, 'custom_unset')
+      end
+
+      let(:u_custom_notification_enabled) do
+        user = create_user_with_notification(:custom, 'custom_enabled')
+        update_custom_notification(:success_pipeline, user, resource: project)
+        update_custom_notification(:failed_pipeline, user, resource: project)
+        user
+      end
+
+      let(:u_custom_notification_disabled) do
+        user = create_user_with_notification(:custom, 'custom_disabled')
+        update_custom_notification(:success_pipeline, user, resource: project, value: false)
+        update_custom_notification(:failed_pipeline, user, resource: project, value: false)
+        user
+      end
 
       let(:commit) { project.commit }
-      let(:pipeline) do
-        create(:ci_pipeline, :success,
+
+      def create_pipeline(user, status)
+        create(:ci_pipeline, status,
                project: project,
-               user: current_user,
+               user: user,
                ref: 'refs/heads/master',
                sha: commit.id,
                before_sha: '00000000')
       end
 
       before do
-        project.add_master(current_user)
         project.add_master(u_member)
+        project.add_master(u_watcher)
+        project.add_master(u_custom_notification_unset)
+        project.add_master(u_custom_notification_enabled)
+        project.add_master(u_custom_notification_disabled)
+
         reset_delivered_emails!
       end
 
-      context 'without custom recipients' do
-        it 'notifies the pipeline user' do
-          notification.pipeline_finished(pipeline)
+      context 'with a successful pipeline' do
+        context 'when the creator has default settings' do
+          before do
+            pipeline = create_pipeline(u_member, :success)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'notifies nobody' do
+            should_not_email_anyone
+          end
+        end
+
+        context 'when the creator has watch set' do
+          before do
+            pipeline = create_pipeline(u_watcher, :success)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'notifies nobody' do
+            should_not_email_anyone
+          end
+        end
+
+        context 'when the creator has custom notifications, but without any set' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_unset, :success)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'notifies nobody' do
+            should_not_email_anyone
+          end
+        end
+
+        context 'when the creator has custom notifications disabled' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_disabled, :success)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'notifies nobody' do
+            should_not_email_anyone
+          end
+        end
+
+        context 'when the creator has custom notifications enabled' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_enabled, :success)
+            notification.pipeline_finished(pipeline)
+          end
 
-          should_only_email(current_user, kind: :bcc)
+          it 'emails only the creator' do
+            should_only_email(u_custom_notification_enabled, kind: :bcc)
+          end
         end
       end
 
-      context 'with custom recipients' do
-        it 'notifies the custom recipients' do
-          users = [u_member, u_other]
-          notification.pipeline_finished(pipeline, users.map(&:notification_email))
+      context 'with a failed pipeline' do
+        context 'when the creator has no custom notification set' do
+          before do
+            pipeline = create_pipeline(u_member, :failed)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'emails only the creator' do
+            should_only_email(u_member, kind: :bcc)
+          end
+        end
+
+        context 'when the creator has watch set' do
+          before do
+            pipeline = create_pipeline(u_watcher, :failed)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'emails only the creator' do
+            should_only_email(u_watcher, kind: :bcc)
+          end
+        end
+
+        context 'when the creator has custom notifications, but without any set' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_unset, :failed)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'emails only the creator' do
+            should_only_email(u_custom_notification_unset, kind: :bcc)
+          end
+        end
+
+        context 'when the creator has custom notifications disabled' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_disabled, :failed)
+            notification.pipeline_finished(pipeline)
+          end
 
-          should_only_email(*users, kind: :bcc)
+          it 'notifies nobody' do
+            should_not_email_anyone
+          end
+        end
+
+        context 'when the creator has custom notifications set' do
+          before do
+            pipeline = create_pipeline(u_custom_notification_enabled, :failed)
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'emails only the creator' do
+            should_only_email(u_custom_notification_enabled, kind: :bcc)
+          end
+        end
+
+        context 'when the creator has no read_build access' do
+          before do
+            pipeline = create_pipeline(u_member, :failed)
+            project.update(public_builds: false)
+            project.team.truncate
+            notification.pipeline_finished(pipeline)
+          end
+
+          it 'does not send emails' do
+            should_not_email_anyone
+          end
         end
       end
     end
@@ -1385,9 +1517,9 @@ describe NotificationService, services: true do
 
   # Create custom notifications
   # When resource is nil it means global notification
-  def update_custom_notification(event, user, resource = nil)
+  def update_custom_notification(event, user, resource: nil, value: true)
     setting = user.notification_settings_for(resource)
-    setting.events[event] = true
+    setting.events[event] = value
     setting.save
   end
 
diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb
index 5a7ce2e08c482fc9be21530a0c7fb68ed6bbdc02..139032d77bd49365910b3e223c39277486929024 100644
--- a/spec/workers/pipeline_notification_worker_spec.rb
+++ b/spec/workers/pipeline_notification_worker_spec.rb
@@ -3,131 +3,19 @@ require 'spec_helper'
 describe PipelineNotificationWorker do
   include EmailHelpers
 
-  let(:pipeline) do
-    create(:ci_pipeline,
-           project: project,
-           sha: project.commit('master').sha,
-           user: pusher,
-           status: status)
-  end
-
-  let(:project) { create(:project, :repository, public_builds: false) }
-  let(:user) { create(:user) }
-  let(:pusher) { user }
-  let(:watcher) { pusher }
+  let(:pipeline) { create(:ci_pipeline) }
 
   describe '#execute' do
-    before do
-      reset_delivered_emails!
-      pipeline.project.team << [pusher, Gitlab::Access::DEVELOPER]
-    end
-
-    context 'when watcher has developer access' do
-      before do
-        pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER]
-      end
-
-      shared_examples 'sending emails' do
-        it 'sends emails' do
-          perform_enqueued_jobs do
-            subject.perform(pipeline.id)
-          end
-
-          emails = ActionMailer::Base.deliveries
-          actual = emails.flat_map(&:bcc).sort
-          expected_receivers = receivers.map(&:email).uniq.sort
-
-          expect(actual).to eq(expected_receivers)
-          expect(emails.size).to eq(1)
-          expect(emails.last.subject).to include(email_subject)
-        end
-      end
-
-      context 'with success pipeline' do
-        let(:status) { 'success' }
-        let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" }
-        let(:receivers) { [pusher, watcher] }
-
-        it_behaves_like 'sending emails'
-
-        context 'with pipeline from someone else' do
-          let(:pusher) { create(:user) }
-          let(:watcher) { user }
-
-          context 'with success pipeline notification on' do
-            before do
-              watcher.global_notification_setting.
-                update(level: 'custom', success_pipeline: true)
-            end
-
-            it_behaves_like 'sending emails'
-          end
-
-          context 'with success pipeline notification off' do
-            let(:receivers) { [pusher] }
+    it 'calls NotificationService#pipeline_finished when the pipeline exists' do
+      expect(NotificationService).to receive_message_chain(:new, :pipeline_finished)
 
-            before do
-              watcher.global_notification_setting.
-                update(level: 'custom', success_pipeline: false)
-            end
-
-            it_behaves_like 'sending emails'
-          end
-        end
-
-        context 'with failed pipeline' do
-          let(:status) { 'failed' }
-          let(:email_subject) { "Pipeline ##{pipeline.id} has failed" }
-
-          it_behaves_like 'sending emails'
-
-          context 'with pipeline from someone else' do
-            let(:pusher) { create(:user) }
-            let(:watcher) { user }
-
-            context 'with failed pipeline notification on' do
-              before do
-                watcher.global_notification_setting.
-                  update(level: 'custom', failed_pipeline: true)
-              end
-
-              it_behaves_like 'sending emails'
-            end
-
-            context 'with failed pipeline notification off' do
-              let(:receivers) { [pusher] }
-
-              before do
-                watcher.global_notification_setting.
-                  update(level: 'custom', failed_pipeline: false)
-              end
-
-              it_behaves_like 'sending emails'
-            end
-          end
-        end
-      end
+      subject.perform(pipeline.id)
     end
 
-    context 'when watcher has no read_build access' do
-      let(:status) { 'failed' }
-      let(:email_subject) { "Pipeline ##{pipeline.id} has failed" }
-      let(:watcher) { create(:user) }
-
-      before do
-        pipeline.project.team << [watcher, Gitlab::Access::GUEST]
-
-        watcher.global_notification_setting.
-          update(level: 'custom', failed_pipeline: true)
-
-        perform_enqueued_jobs do
-          subject.perform(pipeline.id)
-        end
-      end
+    it 'does nothing when the pipeline does not exist' do
+      expect(NotificationService).not_to receive(:new)
 
-      it 'does not send emails' do
-        should_only_email(pusher, kind: :bcc)
-      end
+      subject.perform(Ci::Pipeline.maximum(:id).to_i.succ)
     end
   end
 end