diff --git a/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue b/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue
index 3c94e2d38e9d7a7f5d689e98a568e4a0d7261691..2ccff5dca6f3252cd89dc7721dc1e5f70aeed6ed 100644
--- a/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue
+++ b/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue
@@ -60,7 +60,7 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v
     </template>
 
     <!-- eslint-disable-next-line vue/valid-v-slot -->
-    <template #datetimeStart.field="{ attrs, on }">
+    <template #datetimeStart.field="{ attrs, on, item }">
       <v-slide-y-transition appear>
         <div aria-required="true">
           <date-time-field
@@ -69,13 +69,14 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v
             v-bind="attrs"
             v-on="on"
             required
+            :max="item.datetimeEnd"
           />
         </div>
       </v-slide-y-transition>
     </template>
 
     <!-- eslint-disable-next-line vue/valid-v-slot -->
-    <template #datetimeEnd.field="{ attrs, on }">
+    <template #datetimeEnd.field="{ attrs, on, item }">
       <v-slide-y-transition appear>
         <div aria-required="true">
           <date-time-field
@@ -84,6 +85,9 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v
             v-bind="attrs"
             v-on="on"
             required
+            :min="
+              $parseISODate(item.datetimeStart).plus({ minutes: 1 }).toISO()
+            "
           />
         </div>
       </v-slide-y-transition>
diff --git a/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py b/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd1620e7d5910bbc79d76197f1fe8b622fd280c5
--- /dev/null
+++ b/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py
@@ -0,0 +1,23 @@
+from django.db import migrations, models
+from django.db.models import F, Q
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0070_oauth_token_checksum'),
+    ]
+
+    operations = [
+        migrations.AddConstraint(
+            model_name='calendarevent',
+            constraint=models.CheckConstraint(check=Q(datetime_end__gt=F('datetime_start')),
+                                              name="datetime_start_before_end"
+            ),
+        ),
+        migrations.AddConstraint(
+            model_name='calendarevent',
+            constraint=models.CheckConstraint(check=Q(date_end__gt=F('date_start')),
+                                              name="date_start_before_end"
+            ),
+        ),
+    ]
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 6a813fa84be2a47dcfe8ce4bfe73f0d6376c1f7f..c02ec1548928f459347df404d6b1a129e9924dc3 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -15,7 +15,7 @@ from django.contrib.postgres.fields import ArrayField
 from django.core.exceptions import ValidationError
 from django.core.validators import MaxValueValidator
 from django.db import models
-from django.db.models import Q, QuerySet
+from django.db.models import F, Q, QuerySet
 from django.dispatch import receiver
 from django.forms.widgets import Media
 from django.http import HttpRequest
@@ -1709,6 +1709,12 @@ class CalendarEvent(CalendarEventMixin, ExtensiblePolymorphicModel, RecurrenceMo
                 check=~Q(datetime_end__isnull=True, date_end__isnull=True),
                 name="datetime_end_or_date_end",
             ),
+            models.CheckConstraint(
+                check=Q(datetime_end__gt=F("datetime_start")), name="datetime_start_before_end"
+            ),
+            models.CheckConstraint(
+                check=Q(date_end__gt=F("date_start")), name="date_start_before_end"
+            ),
             models.CheckConstraint(
                 check=~(Q(datetime_start__isnull=False, timezone="") & ~Q(recurrences="")),
                 name="timezone_if_datetime_start_and_recurring",