diff --git a/core/src/main/java/se/su/dsv/scipro/grading/GradingReportTemplateUpdate.java b/core/src/main/java/se/su/dsv/scipro/grading/GradingReportTemplateUpdate.java
index 92fc554904..ce7a1b70aa 100644
--- a/core/src/main/java/se/su/dsv/scipro/grading/GradingReportTemplateUpdate.java
+++ b/core/src/main/java/se/su/dsv/scipro/grading/GradingReportTemplateUpdate.java
@@ -10,28 +10,28 @@ public record GradingReportTemplateUpdate(
         LocalDate validFrom,
         @Nullable String note,
         String failingGrade,
-        List<Grade> grades,
+        List<GradeLimit> gradeLimits,
         List<Criteria> criteria)
 {
     public GradingReportTemplateUpdate {
         Objects.requireNonNull(validFrom, "Valid from must not be null");
         Objects.requireNonNull(failingGrade, "Failing grade must not be null");
-        Objects.requireNonNull(grades, "Grades must not be null");
+        Objects.requireNonNull(gradeLimits, "Grades must not be null");
         Objects.requireNonNull(criteria, "Criteria must not be null");
 
-        for (Grade grade1 : grades) {
-            for (Grade grade2 : grades) {
-                if (grade1 != grade2 && grade1.minimumPoints() == grade2.minimumPoints()) {
+        for (GradeLimit gradeLimit1 : gradeLimits) {
+            for (GradeLimit gradeLimit2 : gradeLimits) {
+                if (gradeLimit1 != gradeLimit2 && gradeLimit1.minimumPoints() == gradeLimit2.minimumPoints()) {
                     throw new IllegalArgumentException("Duplicate minimum points on grades: %s and %s".formatted(
-                            grade1.grade(),
-                            grade2.grade()));
+                            gradeLimit1.grade(),
+                            gradeLimit2.grade()));
                 }
             }
         }
     }
 
-    public record Grade(String grade, int minimumPoints) {
-        public Grade {
+    public record GradeLimit(String grade, int minimumPoints) {
+        public GradeLimit {
             Objects.requireNonNull(grade, "Grade must not be null");
         }
     }
diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java b/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java
new file mode 100644
index 0000000000..49d6b60097
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java
@@ -0,0 +1,46 @@
+package se.su.dsv.scipro.report;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name = "grading_report_template_grade_limits")
+public class GradeLimit {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "grade")
+    private String grade;
+
+    @Column(name = "lower_limit")
+    private int lowerLimit;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public int getLowerLimit() {
+        return lowerLimit;
+    }
+
+    public void setLowerLimit(int lowerLimit) {
+        this.lowerLimit = lowerLimit;
+    }
+}
diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java
index c6aa3a09a3..a4b56f3b1d 100644
--- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java
+++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java
@@ -9,6 +9,7 @@ import se.su.dsv.scipro.system.User;
 import jakarta.persistence.*;
 
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -40,6 +41,10 @@ public class GradingReportTemplate extends DomainObject {
     @Column(name = "failing_grade")
     private String failingGrade;
 
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
+    @JoinColumn(name = "grading_report_template_id")
+    private Collection<GradeLimit> gradeLimits = new ArrayList<>();
+
     protected GradingReportTemplate() {
 
     }
@@ -116,6 +121,14 @@ public class GradingReportTemplate extends DomainObject {
         this.failingGrade = failingGrade;
     }
 
+    public Collection<GradeLimit> getGradeLimits() {
+        return gradeLimits;
+    }
+
+    public void setGradeLimits(Collection<GradeLimit> gradeLimits) {
+        this.gradeLimits = gradeLimits;
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (o == this) return true;
diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java
index d793b7c16e..316b59f515 100644
--- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java
@@ -93,6 +93,14 @@ public class GradingReportTemplateRepoImpl extends GenericRepo<GradingReportTemp
             }
         }
 
+        gradingReportTemplate.getGradeLimits().clear();
+        for (var grade : update.gradeLimits()) {
+            GradeLimit gradeLimit = new GradeLimit();
+            gradeLimit.setGrade(grade.grade());
+            gradeLimit.setLowerLimit(grade.minimumPoints());
+            gradingReportTemplate.getGradeLimits().add(gradeLimit);
+        }
+
         return save(gradingReportTemplate);
     }
 
diff --git a/core/src/main/resources/db/migration/V391__grade_limits_on_grading_templates.sql b/core/src/main/resources/db/migration/V391__grade_limits_on_grading_templates.sql
new file mode 100644
index 0000000000..80a2cc6439
--- /dev/null
+++ b/core/src/main/resources/db/migration/V391__grade_limits_on_grading_templates.sql
@@ -0,0 +1,10 @@
+CREATE TABLE `grading_report_template_grade_limits` (
+    `id` BIGINT NOT NULL AUTO_INCREMENT,
+    `grading_report_template_id` BIGINT, -- can't be NOT NULL because of Hibernate using an INSERT followed by an UPDATE
+    `grade` VARCHAR(32) NOT NULL,
+    `lower_limit` INT NOT NULL,
+    PRIMARY KEY (`id`),
+    UNIQUE KEY `UK_one_grade_per_template` (`grading_report_template_id`, `grade`),
+    FOREIGN KEY `FK_grade_limit_grading_report_template `(`grading_report_template_id`)
+        REFERENCES `grading_report_template` (`id`) ON DELETE CASCADE
+);
diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java
index c8ca35b503..3b75b4ce2a 100644
--- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java
+++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/AdminGradingTemplateEditPage.java
@@ -67,7 +67,7 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
     }
 
     private GradingReportTemplateUpdate toUpdate(EditingGradingTemplate editingGradingTemplate) {
-        List<GradingReportTemplateUpdate.Grade> grades = editingGradingTemplate
+        List<GradingReportTemplateUpdate.GradeLimit> gradeLimits = editingGradingTemplate
                 .getGradeLimits()
                 .getGradeLimits()
                 .stream()
@@ -82,7 +82,7 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
                 editingGradingTemplate.getValidFrom(),
                 editingGradingTemplate.getNote(),
                 editingGradingTemplate.getGradeLimits().getFailingGrade(),
-                grades,
+                gradeLimits,
                 criteria);
     }
 
@@ -117,8 +117,8 @@ public class AdminGradingTemplateEditPage extends AbstractAdminProjectPage imple
         };
     }
 
-    private GradingReportTemplateUpdate.Grade toGrade(GradeLimits.GradeLimit gradeLimit) {
-        return new GradingReportTemplateUpdate.Grade(
+    private GradingReportTemplateUpdate.GradeLimit toGrade(GradeLimits.GradeLimit gradeLimit) {
+        return new GradingReportTemplateUpdate.GradeLimit(
                 gradeLimit.getGrade(),
                 gradeLimit.getLowerLimit());
     }
diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java
index 093455f4d1..cb728abd76 100644
--- a/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java
+++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/grading/GradeLimits.java
@@ -12,6 +12,12 @@ class GradeLimits implements Serializable {
 
     GradeLimits(GradingReportTemplate template) {
         this.gradeLimits = new ArrayList<>();
+        for (var gradeLimit : template.getGradeLimits()) {
+            GradeLimit editableGradeLimit = new GradeLimit();
+            editableGradeLimit.setGrade(gradeLimit.getGrade());
+            editableGradeLimit.setLowerLimit(gradeLimit.getLowerLimit());
+            gradeLimits.add(editableGradeLimit);
+        }
         this.failingGrade = template.getFailingGrade();
     }