diff --git a/app/serializers/topic_view_serializer.rb b/app/serializers/topic_view_serializer.rb
index c033c0ad233..ffe6f706b76 100644
--- a/app/serializers/topic_view_serializer.rb
+++ b/app/serializers/topic_view_serializer.rb
@@ -21,7 +21,6 @@ class TopicViewSerializer < ApplicationSerializer
                         :created_at,
                         :views,
                         :reply_count,
-                        :participant_count,
                         :like_count,
                         :last_posted_at,
                         :visible,
@@ -35,17 +34,18 @@ class TopicViewSerializer < ApplicationSerializer
                         :deleted_at,
                         :pending_posts_count,
                         :user_id,
-                        :pm_with_non_human_user?
+                        :pm_with_non_human_user?,
+                        :featured_link,
+                        :pinned_globally,
+                        :pinned_at,
+                        :pinned_until
 
   attributes :draft,
              :draft_key,
              :draft_sequence,
              :posted,
              :unpinned,
-             :pinned_globally,
-             :pinned,    # Is topic pinned and viewer hasn't cleared the pin?
-             :pinned_at, # Ignores clear pin
-             :pinned_until,
+             :pinned,
              :details,
              :highest_post_number,
              :last_read_post_number,
@@ -59,10 +59,10 @@ class TopicViewSerializer < ApplicationSerializer
              :bookmarked,
              :message_archived,
              :tags,
-             :featured_link,
              :topic_timer,
              :unicode_title,
-             :message_bus_last_id
+             :message_bus_last_id,
+             :participant_count
 
   # TODO: Split off into proper object / serializer
   def details
@@ -193,10 +193,6 @@ class TopicViewSerializer < ApplicationSerializer
   end
   alias_method :include_posted?, :has_topic_user?
 
-  def pinned_globally
-    object.topic.pinned_globally
-  end
-
   def pinned
     PinnedCheck.pinned?(object.topic, object.topic_user)
   end
@@ -205,14 +201,6 @@ class TopicViewSerializer < ApplicationSerializer
     PinnedCheck.unpinned?(object.topic, object.topic_user)
   end
 
-  def pinned_at
-    object.topic.pinned_at
-  end
-
-  def pinned_until
-    object.topic.pinned_until
-  end
-
   def actions_summary
     result = []
     return [] unless post = object.posts&.first
@@ -243,7 +231,7 @@ class TopicViewSerializer < ApplicationSerializer
   end
 
   def bookmarked
-    object.topic_user.try(:bookmarked)
+    object.topic_user&.bookmarked
   end
 
   def include_pending_posts_count?
@@ -266,10 +254,6 @@ class TopicViewSerializer < ApplicationSerializer
     SiteSetting.topic_featured_link_enabled
   end
 
-  def featured_link
-    object.topic.featured_link
-  end
-
   def include_unicode_title?
     !!(object.topic.title =~ /:([\w\-+]*):/)
   end
@@ -282,6 +266,10 @@ class TopicViewSerializer < ApplicationSerializer
     private_message?(object.topic)
   end
 
+  def participant_count
+    object.participants.size
+  end
+
   private
 
     def private_message?(topic)
diff --git a/lib/topic_view.rb b/lib/topic_view.rb
index 0e73dd8af3c..a1d8b311041 100644
--- a/lib/topic_view.rb
+++ b/lib/topic_view.rb
@@ -276,18 +276,21 @@ class TopicView
   end
 
   def post_counts_by_user
-    @post_counts_by_user ||= Post.where(topic_id: @topic.id)
-      .where("user_id IS NOT NULL")
-      .group(:user_id)
-      .order("count_all DESC")
-      .limit(24)
-      .count
+    @post_counts_by_user ||= begin
+      return {} if @posts.blank?
+      Post.where(id: @posts.pluck(:id))
+        .where("user_id IS NOT NULL")
+        .group(:user_id)
+        .order("count_all DESC")
+        .limit(24)
+        .count
+    end
   end
 
   def participants
     @participants ||= begin
       participants = {}
-      User.where(id: post_counts_by_user.map { |k, v| k }).includes(:primary_group).each { |u| participants[u.id] = u }
+      User.where(id: post_counts_by_user.keys).includes(:primary_group).each { |u| participants[u.id] = u }
       participants
     end
   end
diff --git a/spec/components/topic_view_spec.rb b/spec/components/topic_view_spec.rb
index 22a501e99bb..3e8897ae533 100644
--- a/spec/components/topic_view_spec.rb
+++ b/spec/components/topic_view_spec.rb
@@ -160,13 +160,18 @@ describe TopicView do
     end
 
     context '.post_counts_by_user' do
-      it 'returns the two posters with their counts' do
-        expect(topic_view.post_counts_by_user.to_a).to match_array([[first_poster.id, 2], [coding_horror.id, 1]])
+      it 'returns the two posters with their appropriate counts' do
+        Fabricate(:post, topic: topic, user: coding_horror, post_type: Post.types[:whisper])
+
+        expect(topic_view.post_counts_by_user.to_a).to match_array([[first_poster.id, 2], [coding_horror.id, 2]])
+
+        expect(TopicView.new(topic.id, first_poster).post_counts_by_user.to_a).to match_array([[first_poster.id, 2], [coding_horror.id, 1]])
       end
 
       it "doesn't return counts for posts with authors who have been deleted" do
         p2.user_id = nil
         p2.save!
+
         expect(topic_view.post_counts_by_user.to_a).to match_array([[first_poster.id, 2]])
       end
     end