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.