Ruby on Rails has supported UUID primary keys since Rails 4, but the defaults still favour auto-increment integers. Rails 7.2 tightened the UUID integration — the uuid generator option now sets up PostgreSQL uuid columns correctly without extra configuration. Migrating to UUID v7 requires one additional step: swapping Rails’ built-in SecureRandom.uuid (which generates v4) for a v7 source. The uuidv7 gem provides a drop-in replacement that follows RFC 9562 and keeps B-tree indexes sequential on PostgreSQL and MySQL.
Enabling UUID primary keys in Rails
Set the default primary key type in config/application.rb:
config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
Generate a migration for an existing table:
class AddUuidToPosts < ActiveRecord::Migration[7.2]
def change
add_column :posts, :uuid_id, :uuid, default: -> { "gen_random_uuid()" }, null: false
# After backfilling, swap to UUID v7 default via PostgreSQL 18:
# change_column_default :posts, :uuid_id, from: nil, to: -> { "uuidv7()" }
end
end
Switching from UUID v4 to UUID v7
Add the gem:
# Gemfile
gem 'uuidv7'
Configure the model to use v7:
class ApplicationRecord < ActiveRecord::Base
before_create :set_uuid_v7
private
def set_uuid_v7
self.id ||= UUIDv7.generate
end
end
Alternatively, use a PostgreSQL 18 database default so the ID is assigned at the database layer — this keeps UUID generation consistent for bulk inserts via INSERT INTO ... SELECT that bypass Rails callbacks.
PostgreSQL 18 database default
ALTER TABLE posts
ALTER COLUMN id SET DEFAULT uuidv7();
This ensures every row inserted — from Rails, from a database migration, or from a direct SQL script — gets a time-ordered UUID v7 primary key. The PostgreSQL 18 UUID functions documentation covers uuidv7(), uuid_extract_timestamp(), and the related helper functions.
Index performance comparison
| Primary key type | Insert pattern | Index fragmentation | Cache hit rate |
|---|---|---|---|
SERIAL / BIGSERIAL | Sequential | Minimal | High |
| UUID v4 | Random | High after ~100K rows | Low |
| UUID v7 | Near-sequential | Minimal | High |
UUID v7 matches auto-increment performance on B-tree indexes because new values always land near the end of the index. The PostgreSQL B-tree implementation guide explains why sequential inserts minimise page splits.
Stimulus and Hotwire patterns
When generating UUIDs client-side in Stimulus controllers (for optimistic UI updates), use the browser’s crypto.randomUUID() for v4, or the uuid npm package for v7. The client-generated UUID is sent to Rails, which validates format before inserting:
# Controller
def create
@post = Post.new(post_params)
raise ArgumentError, "Invalid UUID" unless @post.id.match?(/\A[0-9a-f-]{36}\z/i)
@post.save!
end
Further reading
- UUID in Databases — PostgreSQL column types and index behaviour
- UUID v4 vs UUID v7 — choosing between the two versions
- UUID Generation Strategies — client vs server vs database assignment
External references
- uuidv7 gem on RubyGems
- Rails ActiveRecord Migrations guide
- PostgreSQL 18 UUID functions
- RFC 9562 — UUID standard
- GeeksforGeeks — UUID as primary key
Frequently asked questions
How do I enable UUID primary keys in Rails?
Add config.generators.orm :active_record, primary_key_type: :uuid to application.rb, then run rails generate model Post — Rails creates a uuid column as the primary key automatically. For UUID v7, use the activeuuid gem or generate v7 values from PostgreSQL 18's uuidv7() function via a database default.
Does Rails support UUID v7 natively?
Rails itself uses UUID v4 via SecureRandom.uuid. For UUID v7 you need either the uuidv7 gem (Ruby implementation of RFC 9562) or a database-side default on PostgreSQL 18. The database-default approach keeps ID generation consistent regardless of which application server creates the record.
Will UUID primary keys break ActiveRecord associations?
No. ActiveRecord handles UUID primary keys and foreign keys transparently — belongs_to, has_many, and has_and_belongs_to_many all work as long as foreign key columns are also declared as :uuid type. The Rails ActiveRecord guides document the :id option for migrations and the primary_key option for models.