Correction, October 2026: The original example incorrectly treated every Rails 7.2 release as fixed. The release guidance and task below have been corrected.

When upgrading to a newer version of PostgreSQL, I started noticing random merge conflicts in db/structure.sql whenever I ran rails db:migrate. The app uses SQL schema format instead of the default Ruby-based schema.

The culprit? A new addition in PostgreSQL's structure dumps:

\restrict UwjeW0L2LmcAYzRcF7mQvbj8424RiEhd5GN4cRvjlLTiknOxUKFNjvE5bEz80JQ
\unrestrict UwjeW0L2LmcAYzRcF7mQvbj8424RiEhd5GN4cRvjlLTiknOxUKFNjvE5bEz80JQ

These lines appear at the top and in the middle of the dump file, and the random tokens change every time. After every migration, db/structure.sql would show meaningless changes like this during a git rebase:

-\restrict UwjeW0L2LmcAYzRcF7mQvbj8424RiEhd5GN4cRvjlLTiknOxUKFNjvE5bEz80JQ
+\restrict TAXaYefQ7OaPsbhTIwM0eA6r8S102Jqiy0mRQfQXQQmIdA9fqI7q4LFmKpchNqQ

Background: Why These Lines Exist

PostgreSQL 17.6 and the corresponding updates to earlier supported branches introduced \restrict and \unrestrict as part of the fix for CVE-2025-8714. pg_dump writes these commands into a plain-text dump. When psql restores it, they enter and leave a restricted mode that blocks potentially dangerous meta-commands. A new random key is generated for each dump.

The workaround below is for a trusted development database’s checked-in schema file. It is not a general cleanup step for backups or dumps from untrusted databases, where the restriction is a security protection.

You can learn more from the official documentation and release notes:

The Fix

Upgrade Rails if possible: the cleanup is included in Rails 7.2.3, 8.0.3, and 8.1. For an older version that still emits these lines, this task cleans up a single database’s default db/structure.sql after a schema dump. Adapt the path and hook if you use multiple databases or a custom schema location.

# lib/tasks/database.rake
# frozen_string_literal: true

# Legacy workaround for a trusted, single-database development schema dump.
# Rails 7.2.3, 8.0.3 and 8.1+ include this cleanup already.
namespace :db do
  namespace :schema do
    desc 'Remove restrict tokens from the trusted development structure.sql'
    task :remove_restrict_lines do
      path = Rails.root.join('db/structure.sql')
      content = File.read(path)
      cleaned = content.gsub(/^\\(?:un)?restrict[ \t]+[^\r\n]*(?:\r?\n|\z)(?:[ \t]*\r?\n)*/, '')
      unless cleaned == content
        File.write(path, cleaned)
        puts 'Removed \\unrestrict and \\restrict lines from db/structure.sql'
      end
    end
  end
end

Rake::Task['db:schema:dump'].enhance do
  cleanup = Rake::Task['db:schema:remove_restrict_lines']
  cleanup.reenable
  cleanup.invoke
end

Result

Now when I run migrations, Rails automatically removes the noise:

Dumping schema
Removed \unrestrict and \restrict lines from db/structure.sql

And the resulting diff looks clean again:

@@ -3822,6 +3821,7 @@ INSERT INTO "schema_migrations" (version) VALUES
 ('20251007095427'),
 ('20251007095426'),
 ('20251007095425'),
+('20251006100600'),
 ('20250725073614'),
 ('20250325000001'),
 ('20250314011832'),

No more merge conflicts caused by these random tokens.

Rails Update

Rails PR #55510, by Brendan Weibrecht (ZimbiX), added this cleanup. It is present in 7.2.3, 8.0.3, and 8.1. The original 7.2 and 8.0 releases did not include it.

Once your Rails version handles the cleanup, remove the custom task.

Summary

For checked-in schema dumps, upgrading Rails avoids random-token diffs. The task above is a workaround for older Rails versions and a trusted development schema.