diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 97df74b0cfe8c695858bb60f93f16d1a60470e20..2cf9892edc56d09098ff4d5f0dcc8a60368a369a 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -251,9 +251,8 @@ module Ci
       Ci::ProcessPipelineService.new(project, user).execute(self)
     end
 
-    def build_updated
+    def update_status
       with_lock do
-        reload
         case latest_builds_status
         when 'pending' then enqueue
         when 'running' then run
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index ee3396abe045c919538bed02c91fe4c9f2631235..9fa8d17e74ec9ba6fb5fb5f86438dcb11a4e2d65 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -84,13 +84,18 @@ class CommitStatus < ActiveRecord::Base
       commit_status.update_attributes finished_at: Time.now
     end
 
-    after_transition any => [:success, :failed, :canceled] do |commit_status|
-      commit_status.pipeline.try(:process!)
-      true
-    end
-
     after_transition do |commit_status, transition|
-      commit_status.pipeline.try(:build_updated) unless transition.loopback?
+      commit_status.pipeline.try do |pipeline|
+        break if transition.loopback?
+
+        if commit_status.complete?
+          ProcessPipelineWorker.perform_async(pipeline.id)
+        end
+
+        UpdatePipelineWorker.perform_async(pipeline.id)
+      end
+
+      true
     end
 
     after_transition [:created, :pending, :running] => :success do |commit_status|
diff --git a/app/workers/process_pipeline_worker.rb b/app/workers/process_pipeline_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..26ea5f1c24da2c7ba8587676c6477f8d75e08ca6
--- /dev/null
+++ b/app/workers/process_pipeline_worker.rb
@@ -0,0 +1,10 @@
+class ProcessPipelineWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :default
+
+  def perform(pipeline_id)
+    Ci::Pipeline.find_by(id: pipeline_id)
+      .try(:process!)
+  end
+end
diff --git a/app/workers/update_pipeline_worker.rb b/app/workers/update_pipeline_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6ef5678073e7b585bcab50e2778bc067bad7cb83
--- /dev/null
+++ b/app/workers/update_pipeline_worker.rb
@@ -0,0 +1,10 @@
+class UpdatePipelineWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :default
+
+  def perform(pipeline_id)
+    Ci::Pipeline.find_by(id: pipeline_id)
+      .try(:update_status)
+  end
+end
diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb
index 650b410595cd3b60313e1bda5dbd920db929c92c..803cbca584db58e0ad7073ed881e96c679445de7 100644
--- a/db/fixtures/development/14_pipelines.rb
+++ b/db/fixtures/development/14_pipelines.rb
@@ -34,7 +34,7 @@ class Gitlab::Seeder::Pipelines
       rescue ActiveRecord::RecordInvalid
         print 'F'
       ensure
-        pipeline.build_updated
+        pipeline.update_status
       end
     end
   end
diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb
index 5972e7f31c2acc92fc979630aa53b1e5aca358fa..01a95bf49acb465ec9d49243214f46bf7a685409 100644
--- a/spec/features/projects/badges/coverage_spec.rb
+++ b/spec/features/projects/badges/coverage_spec.rb
@@ -59,7 +59,7 @@ feature 'test coverage badge' do
 
     create(:ci_pipeline, opts).tap do |pipeline|
       yield pipeline
-      pipeline.build_updated
+      pipeline.update_status
     end
   end
 
diff --git a/spec/lib/gitlab/badge/coverage/report_spec.rb b/spec/lib/gitlab/badge/coverage/report_spec.rb
index ab0cce6e09104a8a6de11e105f00cf1fa415014b..1547bd3228c0c39c170032814077f180bbdf6967 100644
--- a/spec/lib/gitlab/badge/coverage/report_spec.rb
+++ b/spec/lib/gitlab/badge/coverage/report_spec.rb
@@ -100,7 +100,7 @@ describe Gitlab::Badge::Coverage::Report do
 
     create(:ci_pipeline, opts).tap do |pipeline|
       yield pipeline
-      pipeline.build_updated
+      pipeline.update_status
     end
   end
 end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index cf713684463e203fcecca6cdd8aa39393f4277ee..26dd95bdfec64808069ef327ee1c6cb64cb88760 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -283,7 +283,7 @@ describe HipchatService, models: true do
     context 'build events' do
       let(:pipeline) { create(:ci_empty_pipeline) }
       let(:build) { create(:ci_build, pipeline: pipeline) }
-      let(:data) { Gitlab::DataBuilder::Build.build(build) }
+      let(:data) { Gitlab::DataBuilder::Build.build(build.reload) }
 
       context 'for failed' do
         before { build.drop }
diff --git a/spec/workers/process_pipeline_worker_spec.rb b/spec/workers/process_pipeline_worker_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7b5f98d576326e97abec94a81b7005d0060ada90
--- /dev/null
+++ b/spec/workers/process_pipeline_worker_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe ProcessPipelineWorker do
+  describe '#perform' do
+    context 'when pipeline exists' do
+      let(:pipeline) { create(:ci_pipeline) }
+
+      it 'processes pipeline' do
+        expect_any_instance_of(Ci::Pipeline).to receive(:process!)
+
+        described_class.new.perform(pipeline.id)
+      end
+    end
+
+    context 'when pipeline does not exist' do
+      it 'does not raise exception' do
+        expect { described_class.new.perform(123) }
+          .not_to raise_error
+      end
+    end
+  end
+end
diff --git a/spec/workers/update_pipeline_worker_spec.rb b/spec/workers/update_pipeline_worker_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fadc42b22f045630efd755cbf5a488e5f16ce935
--- /dev/null
+++ b/spec/workers/update_pipeline_worker_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe UpdatePipelineWorker do
+  describe '#perform' do
+    context 'when pipeline exists' do
+      let(:pipeline) { create(:ci_pipeline) }
+
+      it 'updates pipeline status' do
+        expect_any_instance_of(Ci::Pipeline).to receive(:update_status)
+
+        described_class.new.perform(pipeline.id)
+      end
+    end
+
+    context 'when pipeline does not exist' do
+      it 'does not raise exception' do
+        expect { described_class.new.perform(123) }
+          .not_to raise_error
+      end
+    end
+  end
+end