diff --git a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
index 080ff17d1a..46bba3fae8 100644
--- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
+++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
@@ -28,6 +28,7 @@ import se.su.dsv.scipro.file.ProjectFileRepository;
 import se.su.dsv.scipro.file.ProjectFileService;
 import se.su.dsv.scipro.file.ProjectFileServiceImpl;
 import se.su.dsv.scipro.finalseminar.AuthorRepository;
+import se.su.dsv.scipro.finalseminar.ExpireUnfulfilledOppositionImprovementsWorker;
 import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepository;
 import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationServiceImpl;
 import se.su.dsv.scipro.finalseminar.FinalSeminarCreationSubscribers;
@@ -204,6 +205,7 @@ import se.su.dsv.scipro.system.UserRepo;
 import se.su.dsv.scipro.system.UserService;
 import se.su.dsv.scipro.system.UserServiceImpl;
 import se.su.dsv.scipro.thesislink.ExternalLinkServiceImpl;
+import se.su.dsv.scipro.workerthreads.Scheduler;
 import se.su.dsv.scipro.workerthreads.WorkerDataServiceImpl;
 
 @Configuration(proxyBeanMethods = false)
@@ -1167,4 +1169,19 @@ public class CoreConfig {
             notificationController
         );
     }
+
+    @Bean
+    public ExpireUnfulfilledOppositionImprovementsWorker expireUnfulfilledOppositionImprovementsWorker(
+        FinalSeminarOppositionServiceImpl finalSeminarOppositionService
+    ) {
+        return new ExpireUnfulfilledOppositionImprovementsWorker(finalSeminarOppositionService);
+    }
+
+    @Bean
+    public ExpireUnfulfilledOppositionImprovementsWorker.Schedule expireUnfulfilledOppositionImprovementsWorkerSchedule(
+        Scheduler scheduler,
+        Provider<ExpireUnfulfilledOppositionImprovementsWorker> worker
+    ) {
+        return new ExpireUnfulfilledOppositionImprovementsWorker.Schedule(scheduler, worker);
+    }
 }
diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/ExpireUnfulfilledOppositionImprovementsWorker.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/ExpireUnfulfilledOppositionImprovementsWorker.java
new file mode 100644
index 0000000000..9a92f0c18b
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/ExpireUnfulfilledOppositionImprovementsWorker.java
@@ -0,0 +1,32 @@
+package se.su.dsv.scipro.finalseminar;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+import java.util.concurrent.TimeUnit;
+import se.su.dsv.scipro.workerthreads.AbstractWorker;
+import se.su.dsv.scipro.workerthreads.Scheduler;
+
+public class ExpireUnfulfilledOppositionImprovementsWorker extends AbstractWorker {
+
+    private final FinalSeminarOppositionServiceImpl oppositionService;
+
+    public ExpireUnfulfilledOppositionImprovementsWorker(FinalSeminarOppositionServiceImpl oppositionService) {
+        this.oppositionService = oppositionService;
+    }
+
+    @Override
+    protected void doWork() {
+        oppositionService.expireUnfulfilledOppositionImprovements();
+    }
+
+    public static class Schedule {
+
+        @Inject
+        public Schedule(Scheduler scheduler, Provider<ExpireUnfulfilledOppositionImprovementsWorker> worker) {
+            scheduler
+                .schedule("Fail opponents that have not submitted improvements")
+                .runBy(worker)
+                .every(1, TimeUnit.HOURS);
+        }
+    }
+}
diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java
index e636597075..b6e7a348c5 100755
--- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java
+++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java
@@ -11,4 +11,6 @@ import se.su.dsv.scipro.system.User;
 public interface FinalSeminarOppositionRepo
     extends JpaRepository<FinalSeminarOpposition, Long>, QueryDslPredicateExecutor<FinalSeminarOpposition> {
     List<FinalSeminarOpposition> findByOpposingUserAndType(User user, ProjectType projectType);
+
+    Collection<FinalSeminarOpposition> findUnfulfilledOppositionImprovements();
 }
diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepoImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepoImpl.java
index 00ad589634..a48da4e198 100644
--- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepoImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepoImpl.java
@@ -24,4 +24,13 @@ public class FinalSeminarOppositionRepoImpl
             .where(QFinalSeminarOpposition.finalSeminarOpposition.project.projectType.eq(projectType))
             .fetch();
     }
+
+    @Override
+    public Collection<FinalSeminarOpposition> findUnfulfilledOppositionImprovements() {
+        return createQuery()
+            .innerJoin(QFinalSeminarOpposition.finalSeminarOpposition.oppositionReport)
+            .where(QFinalSeminarOpposition.finalSeminarOpposition.improvementsRequestedAt.isNotNull())
+            .where(QFinalSeminarOpposition.finalSeminarOpposition.oppositionReport.submitted.isFalse())
+            .fetch();
+    }
 }
diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java
index 693ed21351..1de2066727 100755
--- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java
@@ -7,6 +7,7 @@ import jakarta.persistence.EntityManager;
 import jakarta.transaction.Transactional;
 import java.time.Clock;
 import java.time.Instant;
+import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 import se.su.dsv.scipro.misc.DaysService;
@@ -65,11 +66,24 @@ public class FinalSeminarOppositionServiceImpl
             throw new PointNotValidException(points, List.of(0, 1));
         }
 
+        FinalSeminarGrade notApproved = criteriaForOpposition.pointsToPass() > points
+            ? FinalSeminarGrade.NOT_APPROVED
+            : FinalSeminarGrade.APPROVED;
+        return internalGradeOpponent(opposition, points, feedback, notApproved);
+    }
+
+    private FinalSeminarOpposition internalGradeOpponent(
+        FinalSeminarOpposition opposition,
+        int points,
+        String feedback,
+        FinalSeminarGrade grade
+    ) {
+        opposition.setGrade(grade);
         opposition.setPoints(points);
         opposition.setFeedback(feedback);
         FinalSeminarOpposition assessedOpposition = finalSeminarOppositionRepository.save(opposition);
 
-        if (criteriaForOpposition.pointsToPass() > points) {
+        if (grade == FinalSeminarGrade.NOT_APPROVED) {
             eventBus.post(new OppositionFailedEvent(assessedOpposition));
         } else {
             eventBus.post(new OppositionApprovedEvent(assessedOpposition));
@@ -128,4 +142,36 @@ public class FinalSeminarOppositionServiceImpl
             return Optional.empty();
         }
     }
+
+    void expireUnfulfilledOppositionImprovements() {
+        Collection<FinalSeminarOpposition> unfulfilledOppositions =
+            finalSeminarOppositionRepository.findUnfulfilledOppositionImprovements();
+
+        Instant now = clock.instant();
+        int workDaysToFixRequestedImprovementsToOppositionReport = finalSeminarSettingsService
+            .getInstance()
+            .getWorkDaysToFixRequestedImprovementsToOppositionReport();
+        for (FinalSeminarOpposition unfulfilledOpposition : unfulfilledOppositions) {
+            Instant deadline = daysService.workDaysAfter(
+                unfulfilledOpposition.getImprovementsRequestedAt(),
+                workDaysToFixRequestedImprovementsToOppositionReport
+            );
+            if (now.isAfter(deadline)) {
+                internalGradeOpponent(
+                    unfulfilledOpposition,
+                    0,
+                    unfulfilledOpposition.getSupervisorCommentForImprovements(),
+                    FinalSeminarGrade.NOT_APPROVED
+                );
+
+                OppositionReport oppositionReport = unfulfilledOpposition.getOppositionReport();
+                if (oppositionReport != null) {
+                    // Lock the report so it's not possible to submit it again
+                    oppositionReport.setSubmitted(true);
+                }
+
+                finalSeminarOppositionRepository.save(unfulfilledOpposition);
+            }
+        }
+    }
 }