diff --git a/CHANGELOG b/CHANGELOG
index 983a219703abf054e036e0ba5b6c232198314839..25acdbcb485d2b8024e2fe4f35a0576153d0f91b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -35,6 +35,7 @@ v 8.5.0 (unreleased)
   - Fixed logo animation on Safari (Roman Rott)
   - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg)
   - In seach autocomplete show only groups and projects you are member of
+  - Title for milestones should be unique (Zeger-Jan van de Weg)
 
 v 8.4.4
   - Update omniauth-saml gem to 1.4.2
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index c9a0ad8b9b667b7ac557e06dad48121481ad2332..9c4476c768e5c3763aff2e02f33da460e3f2db6d 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -34,7 +34,7 @@ class Milestone < ActiveRecord::Base
   scope :closed, -> { with_state(:closed) }
   scope :of_projects, ->(ids) { where(project_id: ids) }
 
-  validates :title, presence: true
+  validates :title, presence: true, uniqueness: { scope: :project_id }
   validates :project, presence: true
 
   strip_attributes :title
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 30a71987d86d6fa572769ce88a40b153a53c31cc..1b1380ce4e2c3e31996ad00d678837a633531de5 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -33,6 +33,20 @@ describe Milestone, models: true do
   let(:milestone) { create(:milestone) }
   let(:issue) { create(:issue) }
 
+  describe "unique milestone title per project" do
+    it "shouldn't accept the same title in a project twice" do
+      new_milestone = Milestone.new(project: milestone.project, title: milestone.title)
+      expect(new_milestone).not_to be_valid
+    end
+
+    it "should accept the same title in another project" do
+      project = build(:project)
+      new_milestone = Milestone.new(project: project, title: milestone.title)
+
+      expect(new_milestone).to be_valid
+    end
+  end
+
   describe "#percent_complete" do
     it "should not count open issues" do
       milestone.issues << issue