diff --git a/AKScheduling/models.py b/AKScheduling/models.py
index bfdb1e16d54a844501082704704239f34d62d429..cabf78e16e38fd5e14b4383958244596fc935ddd 100644
--- a/AKScheduling/models.py
+++ b/AKScheduling/models.py
@@ -1,4 +1,4 @@
-from django.db.models.signals import post_save, m2m_changed
+from django.db.models.signals import post_save, m2m_changed, pre_delete
 from django.dispatch import receiver
 from django.utils.translation import gettext_lazy as _
 
@@ -551,6 +551,19 @@ def akslot_changed_handler(sender, instance: AKSlot, **kwargs):
     update_constraint_violations(new_violations, existing_violations_to_check)
 
 
+@receiver(pre_delete, sender=AKSlot)
+def akslot_deleted_handler(sender, instance: AKSlot, **kwargs):
+    # Manually clean up or remove constraint violations that belong to this slot since there is no cascade deletion
+    # for many2many relationships. Explicitly listening for AK deletion signals is not necessary since they will
+    # transitively trigger this signal and we always set both AK and AKSlot references in a constraint violation
+    print(f"{instance} deleted")
+
+    for cv in instance.constraintviolation_set.all():
+        # Make sure not delete CVs that e.g., show three parallel slots in a single room
+        if cv.ak_slots.count() <= 2:
+            cv.delete()
+
+
 @receiver(post_save, sender=Room)
 def room_changed_handler(sender, instance: Room, **kwargs):
     # Changes might affect: Room size