diff --git a/CHANGELOG b/CHANGELOG
index 750ee1016d82cae52dfe7d8b6a6ed1403827848e..83d422633b57d37c831fe58b5ac520db956a0467 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -36,6 +36,7 @@ v 8.3.0 (unreleased)
   - Use new style for milestone detail page
   - Fix sidebar tooltips when collapsed
   - Prevent possible XSS attack with award-emoji
+  - Upgraded Sidekiq to 4.x
 
 v 8.2.3
   - Fix application settings cache not expiring after changes (Stan Hu)
diff --git a/Gemfile b/Gemfile
index 473770f53e5bc8682e004800e0c024a35b6a37a5..d1ed47d230753512ef654d0304ec4b00a72bfb33 100644
--- a/Gemfile
+++ b/Gemfile
@@ -119,8 +119,9 @@ gem 'acts-as-taggable-on', '~> 3.4'
 
 # Background jobs
 gem 'sinatra', '~> 1.4.4', require: nil
-gem 'sidekiq', '~> 3.5.0'
-gem 'sidekiq-cron', '~> 0.3.0'
+gem 'sidekiq', '~> 4.0'
+gem 'sidekiq-cron', '~> 0.4.0'
+gem 'redis-namespace'
 
 # HTTP requests
 gem "httparty", '~> 0.13.3'
diff --git a/Gemfile.lock b/Gemfile.lock
index 37ba22b7ceb394312b5fcdf11d309fbd4ba1848a..20084d08d26a8649dbd4a020009db3539f14ba12 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -147,6 +147,7 @@ GEM
       execjs
     coffee-script-source (1.10.0)
     colorize (0.7.7)
+    concurrent-ruby (1.0.0)
     connection_pool (2.2.0)
     coveralls (0.8.9)
       json (~> 1.8)
@@ -682,15 +683,15 @@ GEM
       rack
     shoulda-matchers (2.8.0)
       activesupport (>= 3.0.0)
-    sidekiq (3.5.3)
-      celluloid (~> 0.17.2)
+    sidekiq (4.0.1)
+      concurrent-ruby (~> 1.0)
       connection_pool (~> 2.2, >= 2.2.0)
       json (~> 1.0)
       redis (~> 3.2, >= 3.2.1)
-      redis-namespace (~> 1.5, >= 1.5.2)
-    sidekiq-cron (0.3.1)
+    sidekiq-cron (0.4.0)
+      redis-namespace (>= 1.5.2)
       rufus-scheduler (>= 2.0.24)
-      sidekiq (>= 2.17.3)
+      sidekiq (>= 4.0.0)
     simple_oauth (0.1.9)
     simplecov (0.10.0)
       docile (~> 1.1.0)
@@ -934,6 +935,7 @@ DEPENDENCIES
   rblineprof
   rdoc (~> 3.6)
   redcarpet (~> 3.3.3)
+  redis-namespace
   redis-rails (~> 4.0.0)
   request_store (~> 1.2.0)
   rerun (~> 0.10.0)
@@ -951,8 +953,8 @@ DEPENDENCIES
   settingslogic (~> 2.0.9)
   sham_rack
   shoulda-matchers (~> 2.8.0)
-  sidekiq (~> 3.5.0)
-  sidekiq-cron (~> 0.3.0)
+  sidekiq (~> 4.0)
+  sidekiq-cron (~> 0.4.0)
   simplecov (~> 0.10.0)
   sinatra (~> 1.4.4)
   six (~> 0.2.0)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 6e5701e33dae579643fa4b305e111a8f3e9e6f5f..2e3a71912ef6b26600838c8a35c4e142c648f614 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -23,6 +23,14 @@ Sidekiq.configure_server do |config|
   if File.exists?(schedule_file)
     Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
   end
+
+  # Database pool should be at least `sidekiq_concurrency` + 2
+  # For more info, see: https://github.com/mperham/sidekiq/blob/master/4.0-Upgrade.md
+  config = ActiveRecord::Base.configurations[Rails.env] ||
+                Rails.application.config.database_configuration[Rails.env]
+  config['pool'] = Sidekiq.options[:concurrency] + 2
+  ActiveRecord::Base.establish_connection(config)
+  Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{ActiveRecord::Base.connection.pool.instance_variable_get('@size')}")
 end
 
 Sidekiq.configure_client do |config|