diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
index 082d0dd9dc73fc3450d03ebb2c3970f3dce7a6b0..56eb514b26f492bfa9ca258b34c9090c10804792 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
@@ -1138,6 +1138,38 @@ class SchedulingUnitCommonPropertiesMixin:
         '''return the latest possible start time for this unit's project and cycle(s)'''
         return self.project.latest_possible_cycle_stop_time
 
+    def validate_scheduling_constraints(self):
+        '''validate the scheduling_constraints_doc against its template, and for additional consistency checks'''
+        if self.scheduling_constraints_template is None or self.scheduling_constraints_doc is None:
+            return
+
+        self.scheduling_constraints_template.validate_document(self.scheduling_constraints_doc)
+
+        if 'time' in self.scheduling_constraints_doc:
+            if 'between' in self.scheduling_constraints_doc['time']:
+                between_durations = [parser.parse(between["to"], ignoretz=True)-parser.parse(between["from"], ignoretz=True)
+                                     for between in self.scheduling_constraints_doc['time']['between']]
+
+                if any([between_duration < self.specified_main_observation_duration for between_duration in between_durations]):
+                    raise RuleValidationException("A between constraint is shorter than the main observation's duration.")
+
+        if 'sky' in self.scheduling_constraints_doc:
+            if 'transit_offset' in self.scheduling_constraints_doc['sky']:
+                # check if the time between all target transits is not larger than the transit_window_width
+                transit_window_width_seconds = abs(self.scheduling_constraints_doc['sky']['transit_offset']['to'] - self.scheduling_constraints_doc['sky']['transit_offset']['from'])
+                # ToDo: move get_transit_offset_pointings (and similar) methods to Task/SchedulingUnit
+                from lofar.sas.tmss.services.scheduling.constraints import get_transit_offset_pointings
+                for task in self.observation_tasks:
+                    if task.is_target_observation:
+                        pointings = get_transit_offset_pointings(task)
+                        transits = [p.transit_lst for p in pointings]
+                        earliest_transit = min(transits)
+                        latest_transit = max(transits)
+                        delta_transit = datetime.datetime.combine(datetime.date.today(), latest_transit) - datetime.datetime.combine(datetime.date.today(), earliest_transit)
+                        delta_transit_seconds = delta_transit.total_seconds()
+                        if delta_transit_seconds > transit_window_width_seconds:
+                            raise RuleValidationException("time between latest and earliest transit for targets in task id=%s name='%s' su_id=%s is larger than the transit_offset window itself: delta_transit=%dsec > transit_window_width=%ssec" % (task.id, task.name, self.id, delta_transit_seconds, transit_window_width_seconds))
+
 
 class SchedulingUnitDraft(TemplateSchemaMixin, ProjectPropertyMixin, SchedulingUnitCommonPropertiesMixin, RefreshFromDbInvalidatesCachedPropertiesMixin, NamedCommon):
     scheduling_set = ForeignKey('SchedulingSet', related_name='scheduling_unit_drafts', on_delete=CASCADE, help_text='Set to which this scheduling unit draft belongs.')
@@ -1171,9 +1203,8 @@ class SchedulingUnitDraft(TemplateSchemaMixin, ProjectPropertyMixin, SchedulingU
 
         # we intentionally do not add defaults to scheduling_constraints_doc
         # because that would add default items which the user did not specify,
-        # and for scheduling contraints this can have unforeseen sideeffects that the user did not intent.
-        self.annotate_doc_using_template('scheduling_constraints_doc', 'scheduling_constraints_template')
-        self.validate_doc_using_template('scheduling_constraints_doc', 'scheduling_constraints_template')
+        # and for scheduling constraints this can have unforeseen side effects that the user did not intend.
+        self.validate_scheduling_constraints()
 
         super().save(force_insert, force_update, using, update_fields)
 
@@ -1336,17 +1367,9 @@ class SchedulingUnitBlueprint(ProjectPropertyMixin, TemplateSchemaMixin, Schedul
                 if hasattr(self, 'draft'):
                     setattr(self, copy_field, getattr(self.draft, copy_field))
 
-        # enforce fixed_time scheduler when time.at is given
-        # ToDo: do we actually want this? It seems to break some tests.
-        #  I'm still in favor of removing the 'scheduler'='dynamic'/'fixed_time' property,
-        # and making it implicit: if 'time'at' is defined, then it's fixed by definition
-        # and if 'time'at' is not defined, then it's dynamic by definition
-        # if self.scheduling_constraints_doc is not None and self.scheduling_constraints_doc.get('time', {}).get('at') is not None:
-        #     self.scheduling_constraints_doc['scheduler'] = 'fixed_time'
-
         # we intentionally do not add defaults to scheduling_constraints_doc
         # because that would add default items which the user did not specify,
-        # and for scheduling contraints this can have unforeseen sideeffects that the user did not intent.
+        # and for scheduling contraints this can have unforeseen side-effects that the user did not intent.
         # but, we do check the validity of the constraints
         self.validate_scheduling_constraints()
 
@@ -1358,20 +1381,6 @@ class SchedulingUnitBlueprint(ProjectPropertyMixin, TemplateSchemaMixin, Schedul
 
         super().save(force_insert, force_update, using, update_fields)
 
-    def validate_scheduling_constraints(self):
-        '''validate the scheduling_constraints_doc against its template, and for additional consistency checks'''
-        if self.scheduling_constraints_template is None or self.scheduling_constraints_doc is None:
-            return
-
-        self.scheduling_constraints_template.validate_document(self.scheduling_constraints_doc)
-
-        if 'time' in self.scheduling_constraints_doc:
-            if 'between' in self.scheduling_constraints_doc['time']:
-                between_durations = [parser.parse(between["to"], ignoretz=True)-parser.parse(between["from"], ignoretz=True)
-                                     for between in self.scheduling_constraints_doc['time']['between']]
-
-                if any([between_duration < self.specified_main_observation_duration for between_duration in between_durations]):
-                    raise RuleValidationException("A between constraint is shorter than the main observation's duration.")
 
     @property
     def tasks(self) -> QuerySet:
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/tasks.py b/SAS/TMSS/backend/src/tmss/tmssapp/tasks.py
index 97faa90d06c50b6d115cff6da144d4472d49b5d3..4aab0b865a25b65e95051e876c79b3a3ce308536 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/tasks.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/tasks.py
@@ -435,6 +435,9 @@ def update_task_graph_from_specifications_doc(scheduling_unit_draft: models.Sche
             scheduling_unit_draft.scheduling_constraints_doc = specifications_doc['scheduling_constraints_doc']
             scheduling_unit_draft.save()
 
+        # finally, check the scheduling_constraints (may raise, reverting the transaction)
+        scheduling_unit_draft.validate_scheduling_constraints()
+
     scheduling_unit_draft.refresh_from_db()
     return scheduling_unit_draft
 
@@ -642,6 +645,9 @@ def update_task_blueprints_and_subtasks_graph_from_draft(scheduling_unit_bluepri
         # and apply
         update_subtasks_start_times_for_scheduling_unit(scheduling_unit_blueprint, initial_scheduled_start_time)
 
+        # finally, check the scheduling_constraints (may raise, reverting the transaction)
+        scheduling_unit_blueprint.validate_scheduling_constraints()
+
     # refresh so all related fields are updated.
     scheduling_unit_blueprint.refresh_from_db()