diff --git a/scipost_django/forums/admin.py b/scipost_django/forums/admin.py
index 089438aeca1951a939b1f1e6ab364e5184edfd0f..4e0d4f504986f46af49a8dfc3c50f5b715025a57 100644
--- a/scipost_django/forums/admin.py
+++ b/scipost_django/forums/admin.py
@@ -32,7 +32,8 @@ admin.site.register(Meeting, MeetingAdmin)
 
 
 class PostAdmin(admin.ModelAdmin):
-    search_fields = ["posted_by", "subject", "text"]
+    list_display = ["anchor", "posted_by", "posted_on"]
+    search_fields = ["posted_by__last_name", "subject", "text"]
     autocomplete_fields = [
         "posted_by",
         "vetted_by",
@@ -43,7 +44,7 @@ admin.site.register(Post, PostAdmin)
 
 
 class MotionAdmin(admin.ModelAdmin):
-    search_fields = ["posted_by", "subject", "text"]
+    search_fields = ["posted_by__last_name", "subject", "text"]
     autocomplete_fields = [
         "posted_by",
         "vetted_by",
diff --git a/scipost_django/forums/apps.py b/scipost_django/forums/apps.py
index a4baef8f50ff54652333a12f6fa80437f4689191..f6a57021962547e6b525c4b823a6e15d554fb4a0 100644
--- a/scipost_django/forums/apps.py
+++ b/scipost_django/forums/apps.py
@@ -1,5 +1,24 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
 from django.apps import AppConfig
+from django.db.models.signals import post_save, post_delete
 
 
 class ForumsConfig(AppConfig):
     name = "forums"
+
+    def ready(self):
+        super().ready()
+
+        from . import signals
+        from forums.models import Post
+        post_save.connect(
+            signals.post_save_update_cfs_in_post_hierarchy,
+            sender=Post,
+        )
+        post_delete.connect(
+            signals.post_delete_update_cfs_in_post_hierarchy,
+            sender=Post,
+        )
diff --git a/scipost_django/forums/management/commands/update_forum_cfs.py b/scipost_django/forums/management/commands/update_forum_cfs.py
new file mode 100644
index 0000000000000000000000000000000000000000..72f00c25f34de1fe257025fe4a99ed82d30a3154
--- /dev/null
+++ b/scipost_django/forums/management/commands/update_forum_cfs.py
@@ -0,0 +1,22 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.core.management.base import BaseCommand
+
+from forums.models import Forum
+
+
+class Command(BaseCommand):
+    help = (
+        "For all Forum instances, this updates the calculated fields."
+    )
+
+    def handle(self, *args, **kwargs):
+        for forum in Forum.objects.all():
+            forum.update_cfs()
+        self.stdout.write(
+            self.style.SUCCESS(
+                "Successfully updated Forum calculated fields"
+            )
+        )
diff --git a/scipost_django/forums/management/commands/update_post_cfs.py b/scipost_django/forums/management/commands/update_post_cfs.py
new file mode 100644
index 0000000000000000000000000000000000000000..67a6c2fdf1042f70da6b22b2e0a283a41c27f36c
--- /dev/null
+++ b/scipost_django/forums/management/commands/update_post_cfs.py
@@ -0,0 +1,22 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.core.management.base import BaseCommand
+
+from forums.models import Post
+
+
+class Command(BaseCommand):
+    help = (
+        "For all Post instances, this updates the calculated fields."
+    )
+
+    def handle(self, *args, **kwargs):
+        for post in Post.objects.all():
+            post.update_cfs()
+        self.stdout.write(
+            self.style.SUCCESS(
+                "Successfully updated Post calculated fields"
+            )
+        )
diff --git a/scipost_django/forums/migrations/0015_auto_20230130_0459.py b/scipost_django/forums/migrations/0015_auto_20230130_0459.py
new file mode 100644
index 0000000000000000000000000000000000000000..8494d75c3675f8bea849e3cb979d0e3545ad0e94
--- /dev/null
+++ b/scipost_django/forums/migrations/0015_auto_20230130_0459.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.16 on 2023-01-30 03:59
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('forums', '0014_auto_20230129_1918'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='post',
+            name='cf_latest_followup_in_hierarchy',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='latest_followup_in_hierarchy_of', to='forums.post'),
+        ),
+        migrations.AddField(
+            model_name='post',
+            name='cf_nr_followups',
+            field=models.PositiveSmallIntegerField(blank=True, null=True),
+        ),
+    ]
diff --git a/scipost_django/forums/migrations/0016_forum_cf_nr_posts.py b/scipost_django/forums/migrations/0016_forum_cf_nr_posts.py
new file mode 100644
index 0000000000000000000000000000000000000000..4f4cc712dceeab848e11b56f9d436fbcc756672c
--- /dev/null
+++ b/scipost_django/forums/migrations/0016_forum_cf_nr_posts.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2023-01-30 04:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('forums', '0015_auto_20230130_0459'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='forum',
+            name='cf_nr_posts',
+            field=models.PositiveSmallIntegerField(blank=True, null=True),
+        ),
+    ]
diff --git a/scipost_django/forums/models.py b/scipost_django/forums/models.py
index 3ca9bda519779cdf0eebb44289d58b0165ed1418..f6bf29febe127c9124b7ab446b23cff4f57ef08e 100644
--- a/scipost_django/forums/models.py
+++ b/scipost_django/forums/models.py
@@ -72,6 +72,9 @@ class Forum(models.Model):
         related_query_name="parent_forums",
     )
 
+    # calculated fields
+    cf_nr_posts = models.PositiveSmallIntegerField(blank=True, null=True)
+
     objects = ForumQuerySet.as_manager()
 
     class Meta:
@@ -89,6 +92,11 @@ class Forum(models.Model):
     def get_absolute_url(self):
         return reverse("forums:forum_detail", kwargs={"slug": self.slug})
 
+    def update_cfs(self):
+        self.update_cf_nr_posts()
+        if self.parent:
+            self.parent.update_cfs()
+
     @property
     def nr_posts(self):
         """Recursively counts the number of posts in this Forum."""
@@ -99,6 +107,10 @@ class Forum(models.Model):
             nr += self.posts.all().count()
         return nr
 
+    def update_cf_nr_posts(self):
+        self.cf_nr_posts = self.nr_posts
+        self.save()
+
     def posts_hierarchy_id_list(self):
         id_list = []
         for post in self.posts.all():
@@ -113,14 +125,6 @@ class Forum(models.Model):
         except:
             return None
 
-    # @property
-    # def posts_all(self):
-    #     """
-    #     Return all posts in the hierarchy.
-    #     """
-    #     posts_id_list = self.posts_hierarchy_id_list()
-    #     return Post.objects.filter(id__in=posts_id_list)
-
 
 class Meeting(Forum):
     """
@@ -258,6 +262,16 @@ class Post(models.Model):
     )
     absolute_url = models.URLField(blank=True)
 
+    # calculated fields
+    cf_nr_followups = models.PositiveSmallIntegerField(blank=True, null=True)
+    cf_latest_followup_in_hierarchy = models.ForeignKey(
+        "forums.Post",
+        on_delete=models.SET_NULL,
+        blank=True,
+        null=True,
+        related_name="latest_followup_in_hierarchy_of",
+    )
+
     objects = PostQuerySet.as_manager()
 
     class Meta:
@@ -283,6 +297,12 @@ class Post(models.Model):
             self.save()
         return self.absolute_url
 
+    def update_cfs(self):
+        self.update_cf_nr_followups()
+        self.update_cf_latest_followup_in_hierarchy()
+        if self.parent:
+            self.parent.update_cfs()
+
     @property
     def nr_followups(self):
         nr = 0
@@ -292,6 +312,10 @@ class Post(models.Model):
             nr += self.followup_posts.all().count()
         return nr
 
+    def update_cf_nr_followups(self):
+        self.cf_nr_followups = self.nr_followups
+        self.save()
+
     @property
     def latest_followup(self):
         return self.followup_posts.last()
@@ -307,6 +331,10 @@ class Post(models.Model):
         id_list = self.posts_hierarchy_id_list()
         return Post.objects.filter(pk__in=id_list).exclude(pk=self.id).last()
 
+    def update_cf_latest_followup_in_hierarchy(self):
+        self.cf_latest_followup_in_hierarchy = self.latest_followup_in_hierarchy
+        self.save()
+
     def get_anchor_forum_or_meeting(self):
         """
         Climb back the hierarchy up to the original Forum.
diff --git a/scipost_django/forums/signals.py b/scipost_django/forums/signals.py
new file mode 100644
index 0000000000000000000000000000000000000000..332b08593043b794ada589c8f61c524917fa4bf9
--- /dev/null
+++ b/scipost_django/forums/signals.py
@@ -0,0 +1,33 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.db.models.signals import post_save, post_delete
+from django.dispatch import receiver
+
+from forums.models import Post
+
+
+@receiver(post_save, sender=Post)
+def post_save_update_cfs_in_post_hierarchy(sender, instance, created, **kwargs):
+    """
+    When a Post is created, update all related Post (and Forum) calculated fields.
+    """
+
+    if created:
+        if instance.parent:
+            instance.parent.update_cfs()
+
+
+@receiver(post_delete, sender=Post)
+def post_delete_update_cfs_in_post_hierarchy(sender, instance, **kwargs):
+    """
+    When a Post is deleted, update all related Post (and Forum) calculated fields.
+    """
+
+    if instance.parent:
+        instance.parent.update_cfs()
+    # to cover multi-instance Post deletion in admin,
+    # which might temporarily break recursive climbing of the hierarchy:
+    if instance.anchor:
+        instance.anchor.update_cfs()
diff --git a/scipost_django/forums/templates/forums/forum_detail.html b/scipost_django/forums/templates/forums/forum_detail.html
index dbc75188bafcc4e741a9929a5c293b542eb235f9..308c47364adc5d521beb09d2a2185647883821bd 100644
--- a/scipost_django/forums/templates/forums/forum_detail.html
+++ b/scipost_django/forums/templates/forums/forum_detail.html
@@ -32,7 +32,7 @@
 
 	<span class="d-flex flex-wrap justify-content-between">
 	  <a href="{{ forum.get_absolute_url }}">{{ forum }}</a>
-	  <span class="badge bg-primary rounded-pill">{% with nr_posts=forum.nr_posts %}{{ nr_posts }} post{{ nr_posts|pluralize }}{% endwith %}</span>
+	  <span class="badge bg-primary rounded-pill">{{ forum.cf_nr_posts }} post{{ forum.cf_nr_posts|pluralize }}</span>
 	</span>
       </h2>
 
@@ -124,12 +124,12 @@
 	  <h3>(most recent first)</h3>
 	  <ul>
 	    {% for post in forum.posts_all.all reversed %}
-	    <li>
-	      <a href="{{ post.get_absolute_url }}">{{ post.subject }}</a> posted by {{ post.posted_by.first_name }} {{ post.posted_by.last_name }} on {{ post.posted_on|date:"Y-m-d H:m" }}
-	      {% if post.parent and not post.motion %}
-		- regarding <a href="{{ post.parent.get_absolute_url }}">{{ post.parent }}</a>
-	      {% endif %}
-	    </li>
+	      <li>
+		<a href="{{ post.get_absolute_url }}">{{ post.subject }}</a> posted by {{ post.posted_by.first_name }} {{ post.posted_by.last_name }} on {{ post.posted_on|date:"Y-m-d H:i" }}
+		{% if post.parent and not post.motion %}
+		  - regarding <a href="{{ post.parent.get_absolute_url }}">{{ post.parent }}</a>
+		{% endif %}
+	      </li>
 	    {% endfor %}
 	  </ul>
 	</div>
@@ -149,18 +149,16 @@
 	  <ul>
 	    {% for post in forum.posts_all.anchors %}
 	      <li>
-		<a href="{{ post.get_absolute_url }}">{{ post.subject }}</a> posted by {{ post.posted_by.first_name }} {{ post.posted_by.last_name }} on {{ post.posted_on|date:"Y-m-d H:m" }}
+		<a href="{{ post.get_absolute_url }}">{{ post.subject }}</a> posted by {{ post.posted_by.first_name }} {{ post.posted_by.last_name }} on {{ post.posted_on|date:"Y-m-d H:i" }}
 		<p>
-		  {% with post.nr_followups as nr_followups %}
-		    {{ nr_followups }} followup{{ nr_followups|pluralize }}
-		  {% endwith %}
-		  {% with post.latest_followup_in_hierarchy as latest_followup %}
+		  {{ post.cf_nr_followups }} followup{{ post.cf_nr_followups|pluralize }}
+		  {% with post.cf_latest_followup_in_hierarchy as latest_followup %}
 		    {% if latest_followup %}
 		      ,&emsp;latest: <a href="{{ latest_followup.get_absolute_url }}">
 		      {{ latest_followup.subject }}</a>
 		      posted by {{ latest_followup.posted_by.first_name }}
 		      {{ latest_followup.posted_by.last_name }}
-		      on {{ latest_followup.posted_on|date:"Y-m-d H:m" }}
+		      on {{ latest_followup.posted_on|date:"Y-m-d H:i" }}
 		    {% endif %}
 		  {% endwith %}
 		</p>
diff --git a/scipost_django/organizations/signals.py b/scipost_django/organizations/signals.py
index e3c1f6d935a0292119b19219a39aba98a083f0b7..322b6b4651d212b7aca45ca690755ff884a0b810 100644
--- a/scipost_django/organizations/signals.py
+++ b/scipost_django/organizations/signals.py
@@ -2,7 +2,6 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
 __license__ = "AGPL v3"
 
 
-from django.core.exceptions import ObjectDoesNotExist
 from django.db.models.signals import post_save
 from django.dispatch import receiver
 
diff --git a/scipost_django/scipost/signals.py b/scipost_django/scipost/signals.py
index f02c46a31d041015617362f8af37796103c3173c..6cdf1fb7c8b4e98a995115b80d53ab93eb51a5c7 100644
--- a/scipost_django/scipost/signals.py
+++ b/scipost_django/scipost/signals.py
@@ -2,7 +2,6 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
 __license__ = "AGPL v3"
 
 
-from django.core.exceptions import ObjectDoesNotExist
 from django.db.models.signals import post_save
 from django.dispatch import receiver