diff --git a/db/migrate/20161117114805_remove_undeleted_groups.rb b/db/migrate/20161117114805_remove_undeleted_groups.rb
index ebc2d974ae0a37a083b520b42fec8b62afd610dd..696914f8e4dca6a0fb0837d1c19339530c3bd65d 100644
--- a/db/migrate/20161117114805_remove_undeleted_groups.rb
+++ b/db/migrate/20161117114805_remove_undeleted_groups.rb
@@ -5,6 +5,47 @@ class RemoveUndeletedGroups < ActiveRecord::Migration
   DOWNTIME = false
 
   def up
+    execute <<-EOF.strip_heredoc
+    DELETE FROM projects
+    WHERE namespace_id IN (
+      SELECT id FROM (
+        SELECT id
+        FROM namespaces
+        WHERE deleted_at IS NOT NULL
+      ) namespace_ids
+    );
+    EOF
+
+    if defined?(Gitlab::License)
+      # EE adds these columns but we have to make sure this data is cleaned up
+      # here before we run the DELETE below. An alternative would be patching
+      # this migration in EE but this will only result in a mess and confusing
+      # migrations.
+      execute <<-EOF.strip_heredoc
+      DELETE FROM protected_branch_push_access_levels
+      WHERE group_id IN (
+        SELECT id FROM (
+          SELECT id
+          FROM namespaces
+          WHERE deleted_at IS NOT NULL
+        ) namespace_ids
+      );
+      EOF
+
+      execute <<-EOF.strip_heredoc
+      DELETE FROM protected_branch_merge_access_levels
+      WHERE group_id IN (
+        SELECT id FROM (
+          SELECT id
+          FROM namespaces
+          WHERE deleted_at IS NOT NULL
+        ) namespace_ids
+      );
+      EOF
+    end
+
+    # This removes namespaces that were supposed to be soft deleted but still
+    # reside in the database.
     execute "DELETE FROM namespaces WHERE deleted_at IS NOT NULL;"
   end