diff --git a/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fc438b5cc6b3909c05455a9712f825020b66d603
--- /dev/null
+++ b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml
@@ -0,0 +1,5 @@
+---
+title: Backfill traversal_ids for gitlab-org .com
+merge_request: 57075
+author:
+type: performance
diff --git a/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8cef1f1cc2b364d27562766e519eaf4099b1419c
--- /dev/null
+++ b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+class SetTraversalIdsForGitlabOrgGroupCom < ActiveRecord::Migration[6.0]
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  def up
+    return unless Gitlab.com?
+
+    # namespace ID 9970 is gitlab-org on .com
+    with_lock_retries do
+      execute(<<~SQL)
+        UPDATE
+          namespaces
+        SET
+          traversal_ids = cte.traversal_ids
+        FROM
+          (
+            WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+              VALUES
+                (9970, ARRAY[9970], false)
+              UNION ALL
+              SELECT
+                n.id,
+                cte.traversal_ids || n.id,
+                n.id = ANY(cte.traversal_ids)
+              FROM
+                namespaces n,
+                cte
+              WHERE
+                n.parent_id = cte.id
+                AND NOT cycle
+            )
+            SELECT
+              id,
+              traversal_ids
+            FROM
+              cte FOR
+            UPDATE
+              ) as cte
+        WHERE
+          namespaces.id = cte.id
+          AND namespaces.traversal_ids <> cte.traversal_ids
+      SQL
+    end
+  end
+
+  def down
+    return unless Gitlab.com?
+
+    # namespace ID 9970 is gitlab-org on .com
+    with_lock_retries do
+      execute(<<~SQL)
+        UPDATE
+          namespaces
+        SET
+          traversal_ids = '{}'
+        FROM
+          (
+            WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+              VALUES
+                (9970, ARRAY[9970], false)
+              UNION ALL
+              SELECT
+                n.id,
+                cte.traversal_ids || n.id,
+                n.id = ANY(cte.traversal_ids)
+              FROM
+                namespaces n,
+                cte
+              WHERE
+                n.parent_id = cte.id
+                AND NOT cycle
+            )
+            SELECT
+              id,
+              traversal_ids
+            FROM
+              cte FOR
+            UPDATE
+              ) as cte
+        WHERE
+          namespaces.id = cte.id
+      SQL
+    end
+  end
+end
diff --git a/db/schema_migrations/20210311045139 b/db/schema_migrations/20210311045139
new file mode 100644
index 0000000000000000000000000000000000000000..71026c1b2afcf6ce2378a2a73f73794e86480212
--- /dev/null
+++ b/db/schema_migrations/20210311045139
@@ -0,0 +1 @@
+2387c8a5516aaf8bcf44c9bad45bfc9844d68d2c03330f67773ce046b21a7a6c
\ No newline at end of file