diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 093b80c4f0ef108962d4c1fd003bdbee8f40fe10..57894f2975b0c1d682fcaecaecfee7398ab11188 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -4,7 +4,7 @@ class CommentsController < ApplicationController
   before_action :set_comment, only: [:update, :destroy, :undelete, :show]
   before_action :set_thread, only: [:thread, :thread_rename, :thread_restrict, :thread_unrestrict, :thread_followers]
   before_action :check_privilege, only: [:update, :destroy, :undelete]
-  before_action :check_if_target_post_locked, only: [:create]
+  before_action :check_if_target_post_locked, only: [:create, :post_follow]
   before_action :check_if_parent_post_locked, only: [:update, :destroy]
 
   def create_thread
@@ -40,9 +40,16 @@ class CommentsController < ApplicationController
     end
 
     if success
+      notification = "New comment thread on #{@comment.root.title}: #{@comment_thread.title}"
       unless @comment.post.user == current_user
-        @comment.post.user.create_notification("New comment thread on #{@comment.root.title}: #{@comment_thread.title}",
-                                               helpers.comment_link(@comment))
+        @comment.post.user.create_notification(notification, helpers.comment_link(@comment))
+      end
+
+      ThreadFollower.where(post: @post).each do |tf|
+        unless tf.user == current_user || tf.user == @comment.post.user
+          tf.user.create_notification(notification, helpers.comment_link(@comment))
+        end
+        ThreadFollower.create(user: tf.user, comment_thread: @comment_thread)
       end
 
       apply_pings pings
@@ -245,6 +252,16 @@ class CommentsController < ApplicationController
     end
   end
 
+  def post_follow
+    @post = Post.find(params[:post_id])
+    if CommentThread.post_followed?(@post, current_user)
+      ThreadFollower.where(post: @post, user: current_user).destroy_all
+    else
+      ThreadFollower.create(post: @post, user: current_user)
+    end
+    redirect_to post_path(@post)
+  end
+
   def pingable
     thread = params[:id] == '-1' ? CommentThread.new(post_id: params[:post]) : CommentThread.find(params[:id])
     ids = helpers.get_pingable(thread)
diff --git a/app/models/comment_thread.rb b/app/models/comment_thread.rb
index c4ec2b8e28372b081d690b4fc6eb61c2f4054793..39f5dcf5c81dff6caf17cedb3700eebb5e43882d 100644
--- a/app/models/comment_thread.rb
+++ b/app/models/comment_thread.rb
@@ -32,6 +32,10 @@ class CommentThread < ApplicationRecord
       post.can_access?(user)
   end
 
+  def self.post_followed?(post, user)
+    ThreadFollower.where(post: post, user: user).any?
+  end
+
   private
 
   # Comment author and post author are automatically followed to the thread. Question author is NOT
diff --git a/app/models/thread_follower.rb b/app/models/thread_follower.rb
index 2f66a4842c2871d093a148a315316ed9bf7e12b2..426e1f39430bd6444c213aa78bd36365b73be9ce 100644
--- a/app/models/thread_follower.rb
+++ b/app/models/thread_follower.rb
@@ -1,4 +1,15 @@
 class ThreadFollower < ApplicationRecord
-  belongs_to :comment_thread
+  belongs_to :comment_thread, optional: true
+  belongs_to :post, optional: true
   belongs_to :user
+
+  validate :thread_or_post
+
+  private
+
+  def thread_or_post
+    if comment_thread.nil? && post.nil?
+      errors.add(:base, 'Must refer to either a comment thread or a post.')
+    end
+  end
 end
diff --git a/app/views/posts/_expanded.html.erb b/app/views/posts/_expanded.html.erb
index e4acfdacfae9734f1fe22ae3cea9bf5de85250ff..82733701ff6fe23351d0afc933a5368438a71292 100644
--- a/app/views/posts/_expanded.html.erb
+++ b/app/views/posts/_expanded.html.erb
@@ -455,6 +455,21 @@
           <h4 class="has-margin-0">
             <%= pluralize(public_count, 'comment thread') %>
           </h4>
+          <% if user_signed_in? %>
+            <p class="has-font-size-caption">
+              <% if CommentThread.post_followed?(post, current_user) %>
+                <%= link_to follow_post_comments_path(post_id: post.id), method: :post,
+                            title: 'Don\'t follow new comment threads on this post' do %>
+                  <i class="fas fa-fw fa-minus"></i> unfollow new
+                <% end %>
+              <% else %>
+                <%= link_to follow_post_comments_path(post_id: post.id), method: :post,
+                            title: 'Follow all new comment threads on this post' do %>
+                  <i class="fas fa-fw fa-plus"></i> follow new
+                <% end %>
+              <% end %>
+            </p>
+          <% end %>
           <div class="post--comments-container">
             <%= render 'comments/post', comment_threads: comment_threads.first(5) %>
           </div>
diff --git a/config/routes.rb b/config/routes.rb
index 694164c6de56abfc142cac41545eee02815b9a05..1619878ee6deb23be1a87ae8baa0a443e36fddaf 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -210,6 +210,7 @@ Rails.application.routes.draw do
     post   'thread/:id/unrestrict',        to: 'comments#thread_unrestrict', as: :unrestrict_comment_thread
     get    'thread/:id/followers',         to: 'comments#thread_followers', as: :comment_thread_followers
     get    'post/:post_id',                to: 'comments#post', as: :post_comments
+    post   'post/:post_id/follow',         to: 'comments#post_follow', as: :follow_post_comments
     get    ':id',                          to: 'comments#show', as: :comment
     get    'thread/:id',                   to: 'comments#thread', as: :comment_thread
     post   ':id/edit',                     to: 'comments#update', as: :update_comment
diff --git a/db/migrate/20220913183826_add_post_to_thread_followers.rb b/db/migrate/20220913183826_add_post_to_thread_followers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e24e77b652fb4c73a5fef63cba4f0aba0be13ef8
--- /dev/null
+++ b/db/migrate/20220913183826_add_post_to_thread_followers.rb
@@ -0,0 +1,6 @@
+class AddPostToThreadFollowers < ActiveRecord::Migration[7.0]
+  def change
+    add_reference :thread_followers, :post, null: true, foreign_key: true
+    change_column_null :thread_followers, :comment_thread_id, true
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index ba718100ce390c0d37728cf0b27c304e798b7dd0..9cc021c6d809687d863c2571e039cb81160d2a2f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2022_09_03_174045) do
+ActiveRecord::Schema[7.0].define(version: 2022_09_13_183826) do
   create_table "abilities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
     t.bigint "community_id"
     t.string "name"
@@ -614,7 +614,9 @@ ActiveRecord::Schema[7.0].define(version: 2022_09_03_174045) do
     t.bigint "user_id"
     t.datetime "created_at", precision: nil, null: false
     t.datetime "updated_at", precision: nil, null: false
+    t.bigint "post_id"
     t.index ["comment_thread_id"], name: "index_thread_followers_on_comment_thread_id"
+    t.index ["post_id"], name: "index_thread_followers_on_post_id"
     t.index ["user_id"], name: "index_thread_followers_on_user_id"
   end
 
@@ -761,6 +763,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_09_03_174045) do
   add_foreign_key "suggested_edits", "users", column: "decided_by_id"
   add_foreign_key "tags", "communities"
   add_foreign_key "tags", "tags", column: "parent_id"
+  add_foreign_key "thread_followers", "posts"
   add_foreign_key "user_abilities", "abilities"
   add_foreign_key "user_abilities", "community_users"
   add_foreign_key "users", "users", column: "deleted_by_id"