diff --git a/Gemfile b/Gemfile
index 5117962391ddce777637c92eb2998da47c04e4f9..c3f50ec30c4d68a5f1e0298ad57a7a72435a07d5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -153,7 +153,6 @@ end
 
 group :production do
   gem 'lograge', '~> 0.11'
-  gem 'redis-rails', '~> 5.0'
 end
 
 gem 'concurrent-ruby', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index d2037b3bce254b57fa179189ca8067ad3c47b992..106c13554caa62a1fa7ebafd96b7e941c1c52da6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -491,24 +491,8 @@ GEM
     rdf-normalize (0.4.0)
       rdf (~> 3.1)
     redis (4.2.5)
-    redis-actionpack (5.2.0)
-      actionpack (>= 5, < 7)
-      redis-rack (>= 2.1.0, < 3)
-      redis-store (>= 1.1.0, < 2)
-    redis-activesupport (5.2.0)
-      activesupport (>= 3, < 7)
-      redis-store (>= 1.3, < 2)
     redis-namespace (1.8.1)
       redis (>= 3.0.4)
-    redis-rack (2.1.3)
-      rack (>= 2.0.8, < 3)
-      redis-store (>= 1.2, < 2)
-    redis-rails (5.0.2)
-      redis-actionpack (>= 5.0, < 6)
-      redis-activesupport (>= 5.0, < 6)
-      redis-store (>= 1.2, < 2)
-    redis-store (1.9.0)
-      redis (>= 4, < 5)
     regexp_parser (2.1.1)
     request_store (1.5.0)
       rack (>= 1.4)
@@ -790,7 +774,6 @@ DEPENDENCIES
   rdf-normalize (~> 0.4)
   redis (~> 4.2)
   redis-namespace (~> 1.8)
-  redis-rails (~> 5.0)
   rqrcode (~> 1.2)
   rspec-rails (~> 5.0)
   rspec-sidekiq (~> 3.1)
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 7252234d6a9b107b7da0bcbac50c5db1d990b1a7..6fb5d541997adb1367140a5add11aaa03df797dc 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -158,9 +158,9 @@ class Formatter
           original_url, static_url = emoji
           replacement = begin
             if animate
-              "<img draggable=\"false\" class=\"emojione\" alt=\":#{encode(shortcode)}:\" title=\":#{encode(shortcode)}:\" src=\"#{encode(original_url)}\" />"
+              image_tag(original_url, draggable: false, class: 'emojione', alt: ":#{shortcode}:", title: ":#{shortcode}:")
             else
-              "<img draggable=\"false\" class=\"emojione custom-emoji\" alt=\":#{encode(shortcode)}:\" title=\":#{encode(shortcode)}:\" src=\"#{encode(static_url)}\" data-original=\"#{original_url}\" data-static=\"#{static_url}\" />"
+              image_tag(original_url, draggable: false, class: 'emojione custom-emoji', alt: ":#{shortcode}:", title: ":#{shortcode}:", data: { original: original_url, static: static_url })
             end
           end
           before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : ''
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index 54db892ccc6e767ae4c7d1cf344deeabccf33ed3..9e683b6a161b551478cf1fd616565650e5ff6184 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -4,7 +4,7 @@ class NotificationMailer < ApplicationMailer
   helper :accounts
   helper :statuses
 
-  add_template_helper RoutingHelper
+  helper RoutingHelper
 
   def mention(recipient, notification)
     @me     = recipient
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 95996ba3ff9d8c92fc2423322a041899cb3592c7..68d1c4507e8554e48dfc100bb74fb16ea3b496b2 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -8,7 +8,7 @@ class UserMailer < Devise::Mailer
   helper :instance
   helper :statuses
 
-  add_template_helper RoutingHelper
+  helper RoutingHelper
 
   def confirmation_instructions(user, token, **)
     @resource = user
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 98a6a618f5fe2b76f032eb47e0a8e20d6a5c85f7..3bf9dd483e6da921c989c05c3b3ca13c0d489a85 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -49,12 +49,12 @@ class Notification < ApplicationRecord
   belongs_to :from_account, class_name: 'Account', optional: true
   belongs_to :activity, polymorphic: true, optional: true
 
-  belongs_to :mention,        foreign_type: 'Mention',       foreign_key: 'activity_id', optional: true
-  belongs_to :status,         foreign_type: 'Status',        foreign_key: 'activity_id', optional: true
-  belongs_to :follow,         foreign_type: 'Follow',        foreign_key: 'activity_id', optional: true
-  belongs_to :follow_request, foreign_type: 'FollowRequest', foreign_key: 'activity_id', optional: true
-  belongs_to :favourite,      foreign_type: 'Favourite',     foreign_key: 'activity_id', optional: true
-  belongs_to :poll,           foreign_type: 'Poll',          foreign_key: 'activity_id', optional: true
+  belongs_to :mention,        foreign_key: 'activity_id', optional: true
+  belongs_to :status,         foreign_key: 'activity_id', optional: true
+  belongs_to :follow,         foreign_key: 'activity_id', optional: true
+  belongs_to :follow_request, foreign_key: 'activity_id', optional: true
+  belongs_to :favourite,      foreign_key: 'activity_id', optional: true
+  belongs_to :poll,           foreign_key: 'activity_id', optional: true
 
   validates :type, inclusion: { in: TYPES }
 
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 0791b82ab6ea1393efcb3faff300d998c2ee7fa1..d76361c6027a128ccd5da38361096f5b3c0d5392 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -17,7 +17,7 @@ Rails.application.configure do
   if Rails.root.join('tmp/caching-dev.txt').exist?
     config.action_controller.perform_caching = true
 
-    config.cache_store = :redis_store, ENV['REDIS_URL'], REDIS_CACHE_PARAMS
+    config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS
 
     config.public_file_server.headers = {
       'Cache-Control' => "public, max-age=#{2.days.to_i}",
diff --git a/config/environments/production.rb b/config/environments/production.rb
index aaad2449f23e09c82a2845f82aa3f5e7dc83e47f..81a67902eadb6214bc56fb1ea397ca817957e202 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -52,7 +52,7 @@ Rails.application.configure do
   config.log_tags = [:request_id]
 
   # Use a different cache store in production.
-  config.cache_store = :redis_store, ENV['CACHE_REDIS_URL'], REDIS_CACHE_PARAMS
+  config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS
 
   # Ignore bad email addresses and do not raise email delivery errors.
   # Set this to true and configure the email server for immediate delivery to raise delivery errors.
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 9d348ddd08ea00c1fd2e55b435a3685e893784b3..fc85a3913763595ee44eb41e8715b0cae722448b 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 namespace    = ENV.fetch('REDIS_NAMESPACE') { nil }
-redis_params = { url: ENV['REDIS_URL'] }
+redis_params = { url: ENV['REDIS_URL'], driver: :hiredis }
 
 if namespace
   redis_params[:namespace] = namespace
diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb
index c3c8ff8005d3262244328560c8689ba295bc52b1..3f2a8f7c264da0a87002fc170dbbcb7761532500 100644
--- a/lib/mastodon/redis_config.rb
+++ b/lib/mastodon/redis_config.rb
@@ -27,6 +27,8 @@ namespace       = ENV.fetch('REDIS_NAMESPACE', nil)
 cache_namespace = namespace ? namespace + '_cache' : 'cache'
 
 REDIS_CACHE_PARAMS = {
+  driver: :hiredis,
+  url: ENV['REDIS_URL'],
   expires_in: 10.minutes,
   namespace: cache_namespace,
 }.freeze
diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb
index f7d0b1af54e7ca88f7d0c992b55536821c58f992..ac426b01e635de6fe6819ceda7f7cc68ac62c9d1 100644
--- a/spec/controllers/accounts_controller_spec.rb
+++ b/spec/controllers/accounts_controller_spec.rb
@@ -370,7 +370,7 @@ RSpec.describe AccountsController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it_behaves_like 'cachable response'
@@ -402,7 +402,7 @@ RSpec.describe AccountsController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns public Cache-Control header' do
@@ -428,7 +428,7 @@ RSpec.describe AccountsController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it_behaves_like 'cachable response'
@@ -446,7 +446,7 @@ RSpec.describe AccountsController, type: :controller do
           end
 
           it 'returns application/activity+json' do
-            expect(response.content_type).to eq 'application/activity+json'
+            expect(response.media_type).to eq 'application/activity+json'
           end
 
           it 'returns private Cache-Control header' do
diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb
index ac661e5e1d931a6c212d3def8453d22af56eb5be..d584136ff56dd69715195f6d5b47d258c7a90448 100644
--- a/spec/controllers/activitypub/collections_controller_spec.rb
+++ b/spec/controllers/activitypub/collections_controller_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it_behaves_like 'cachable response'
@@ -88,7 +88,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
           end
 
           it 'returns application/activity+json' do
-            expect(response.content_type).to eq 'application/activity+json'
+            expect(response.media_type).to eq 'application/activity+json'
           end
 
           it_behaves_like 'cachable response'
@@ -116,7 +116,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
             end
 
             it 'returns application/activity+json' do
-              expect(response.content_type).to eq 'application/activity+json'
+              expect(response.media_type).to eq 'application/activity+json'
             end
 
             it 'returns private Cache-Control header' do
@@ -141,7 +141,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do
             end
 
             it 'returns application/activity+json' do
-              expect(response.content_type).to eq 'application/activity+json'
+              expect(response.media_type).to eq 'application/activity+json'
             end
 
             it 'returns private Cache-Control header' do
diff --git a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
index 88f4554c2d6cbd70aa50d12ae06d1216d9eb1929..d373f56bdb0cd2f20690ee8a8dcf765599793b9f 100644
--- a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
+++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController, type: :controll
       end
 
       it 'returns application/activity+json' do
-        expect(response.content_type).to eq 'application/activity+json'
+        expect(response.media_type).to eq 'application/activity+json'
       end
 
       it 'returns orderedItems with followers from example.com' do
diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb
index 84e3a8956027857a2091cb2364fd33cac6e49d31..d23f2c17cbcaca8bd5cc40cb35dec620d4fa58dc 100644
--- a/spec/controllers/activitypub/outboxes_controller_spec.rb
+++ b/spec/controllers/activitypub/outboxes_controller_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns totalItems' do
@@ -85,7 +85,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns orderedItems with public or unlisted statuses' do
@@ -133,7 +133,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns orderedItems with public or unlisted statuses' do
@@ -159,7 +159,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns orderedItems with private statuses' do
@@ -185,7 +185,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns empty orderedItems' do
@@ -210,7 +210,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it 'returns empty orderedItems' do
diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb
index 25025975283e041bbddd970ce30ad4ad2732dca3..bf82fd0207bd12166081108a9e9f5abe0b2e2a43 100644
--- a/spec/controllers/activitypub/replies_controller_spec.rb
+++ b/spec/controllers/activitypub/replies_controller_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
         end
 
         it 'returns application/activity+json' do
-          expect(response.content_type).to eq 'application/activity+json'
+          expect(response.media_type).to eq 'application/activity+json'
         end
 
         it_behaves_like 'cachable response'
@@ -120,7 +120,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
           end
 
           it 'returns application/activity+json' do
-            expect(response.content_type).to eq 'application/activity+json'
+            expect(response.media_type).to eq 'application/activity+json'
           end
 
           it_behaves_like 'cachable response'
diff --git a/spec/controllers/concerns/export_controller_concern_spec.rb b/spec/controllers/concerns/export_controller_concern_spec.rb
index fce129bee2223aadd8624690704289a9ff1ee0d8..1a5e46f8efdacd257b857c1eabcdff392f0c60c9 100644
--- a/spec/controllers/concerns/export_controller_concern_spec.rb
+++ b/spec/controllers/concerns/export_controller_concern_spec.rb
@@ -22,8 +22,8 @@ describe ApplicationController, type: :controller do
       get :index, format: :csv
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'text/csv'
-      expect(response.headers['Content-Disposition']).to eq 'attachment; filename="anonymous.csv"'
+      expect(response.media_type).to eq 'text/csv'
+      expect(response.headers['Content-Disposition']).to start_with 'attachment; filename="anonymous.csv"'
       expect(response.body).to eq user.account.username
     end
 
diff --git a/spec/controllers/well_known/host_meta_controller_spec.rb b/spec/controllers/well_known/host_meta_controller_spec.rb
index 643ba9cd3283aa1b1df379a428364a69395c263e..c02aa0d596d97cbca498fd6563655814c0b0f59e 100644
--- a/spec/controllers/well_known/host_meta_controller_spec.rb
+++ b/spec/controllers/well_known/host_meta_controller_spec.rb
@@ -8,7 +8,7 @@ describe WellKnown::HostMetaController, type: :controller do
       get :show, format: :xml
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/xrd+xml'
+      expect(response.media_type).to eq 'application/xrd+xml'
       expect(response.body).to eq <<XML
 <?xml version="1.0" encoding="UTF-8"?>
 <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
diff --git a/spec/controllers/well_known/keybase_proof_config_controller_spec.rb b/spec/controllers/well_known/keybase_proof_config_controller_spec.rb
index 9067e676debda270ca22c3f0208657eaa1004d5d..00f251c3c67554d3fb423518413e67d00e3d9657 100644
--- a/spec/controllers/well_known/keybase_proof_config_controller_spec.rb
+++ b/spec/controllers/well_known/keybase_proof_config_controller_spec.rb
@@ -8,7 +8,7 @@ describe WellKnown::KeybaseProofConfigController, type: :controller do
       get :show
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/json'
+      expect(response.media_type).to eq 'application/json'
       expect { JSON.parse(response.body) }.not_to raise_exception
     end
   end
diff --git a/spec/controllers/well_known/nodeinfo_controller_spec.rb b/spec/controllers/well_known/nodeinfo_controller_spec.rb
index 12e1fa4159ce0113fadf73d27e19ba9620dd8c60..694bb0fb9fe223d28a0d65718512fc6385d927fe 100644
--- a/spec/controllers/well_known/nodeinfo_controller_spec.rb
+++ b/spec/controllers/well_known/nodeinfo_controller_spec.rb
@@ -8,7 +8,7 @@ describe WellKnown::NodeInfoController, type: :controller do
       get :index
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/json'
+      expect(response.media_type).to eq 'application/json'
 
       json = body_as_json
 
@@ -23,7 +23,7 @@ describe WellKnown::NodeInfoController, type: :controller do
       get :show
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/json'
+      expect(response.media_type).to eq 'application/json'
 
       json = body_as_json
 
diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb
index cf7005b0e79a315b70557b178602093d7b5d46cc..1075456f33685926b4644cbbb45ae0828feeeff9 100644
--- a/spec/controllers/well_known/webfinger_controller_spec.rb
+++ b/spec/controllers/well_known/webfinger_controller_spec.rb
@@ -25,7 +25,7 @@ describe WellKnown::WebfingerController, type: :controller do
       end
 
       it 'returns application/jrd+json' do
-        expect(response.content_type).to eq 'application/jrd+json'
+        expect(response.media_type).to eq 'application/jrd+json'
       end
 
       it 'returns links for the account' do
diff --git a/spec/requests/catch_all_route_request_spec.rb b/spec/requests/catch_all_route_request_spec.rb
index 22ce1cf59f6cb6b6372484a22be051a4ac1f4342..f965f552219fbea7bb868a292a9c5a041f4a6f54 100644
--- a/spec/requests/catch_all_route_request_spec.rb
+++ b/spec/requests/catch_all_route_request_spec.rb
@@ -6,7 +6,7 @@ describe "The catch all route" do
       get "/test"
 
       expect(response.status).to eq 404
-      expect(response.content_type).to eq "text/html"
+      expect(response.media_type).to eq "text/html"
     end
   end
 
@@ -15,7 +15,7 @@ describe "The catch all route" do
       get "/test.test"
 
       expect(response.status).to eq 404
-      expect(response.content_type).to eq "text/html"
+      expect(response.media_type).to eq "text/html"
     end
   end
 end
diff --git a/spec/requests/host_meta_request_spec.rb b/spec/requests/host_meta_request_spec.rb
index beb33a859e58106cb8ac6cba299fbd3d1e0c2fcc..0ca641461371deade82b7e27a9438cb6edea1b8a 100644
--- a/spec/requests/host_meta_request_spec.rb
+++ b/spec/requests/host_meta_request_spec.rb
@@ -6,7 +6,7 @@ describe "The host_meta route" do
       get host_meta_url
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq "application/xrd+xml"
+      expect(response.media_type).to eq "application/xrd+xml"
     end
   end
 end
diff --git a/spec/requests/webfinger_request_spec.rb b/spec/requests/webfinger_request_spec.rb
index 48823714e2087b545719c0f5235ebb3b6ccf6c93..209fda72aad21c43b492f79b3093116c1c84fa2e 100644
--- a/spec/requests/webfinger_request_spec.rb
+++ b/spec/requests/webfinger_request_spec.rb
@@ -8,7 +8,7 @@ describe 'The webfinger route' do
       get webfinger_url(resource: alice.to_webfinger_s)
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/jrd+json'
+      expect(response.media_type).to eq 'application/jrd+json'
     end
   end
 
@@ -17,7 +17,7 @@ describe 'The webfinger route' do
       get webfinger_url(resource: alice.to_webfinger_s, format: :json)
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/jrd+json'
+      expect(response.media_type).to eq 'application/jrd+json'
     end
 
     it 'returns a json response for json accept header' do
@@ -25,7 +25,7 @@ describe 'The webfinger route' do
       get webfinger_url(resource: alice.to_webfinger_s), headers: headers
 
       expect(response).to have_http_status(200)
-      expect(response.content_type).to eq 'application/jrd+json'
+      expect(response.media_type).to eq 'application/jrd+json'
     end
   end
 end