Blog
Wild & Free Tools

Rails UUID Primary Key with PostgreSQL

Last updated: April 2026 5 min read
Quick Answer

Table of Contents

  1. Enable pgcrypto
  2. application.rb Config
  3. Model Migration
  4. Association Gotcha
  5. Model and Queries
  6. Frequently Asked Questions

Rails with PostgreSQL supports UUID primary keys through the pgcrypto extension, which provides the gen_random_uuid() database function. Once configured, Rails generates UUIDs at the database level — no Ruby code change needed per model. The main gotcha is association migrations, which need an explicit UUID type declaration. This guide walks through the complete setup.

Step 1 — Enable the pgcrypto Extension

Create a migration to enable the extension in your PostgreSQL database:

rails generate migration EnablePgcrypto
class EnablePgcrypto < ActiveRecord::Migration[7.1]
  def change
    enable_extension 'pgcrypto'
  end
end
rails db:migrate

The pgcrypto extension adds gen_random_uuid() to PostgreSQL, which generates cryptographically random UUID v4 values. This is what Rails uses as the default value for UUID columns.

If you're on PostgreSQL 13+, you can also use the built-in gen_random_uuid() without the extension — but enabling pgcrypto is the conventional Rails approach and works on all supported PostgreSQL versions.

Step 2 — Configure UUID as Default Primary Key Type

In config/application.rb, tell Rails to use UUID for all generated migrations:

module MyApp
  class Application < Rails::Application
    config.generators do |g|
      g.orm :active_record, primary_key_type: :uuid
    end
  end
end

After this change, every rails generate model command creates a migration with t.uuid :id, default: "gen_random_uuid()", primary_key: true instead of the default integer id. You don't need to repeat this in each migration.

Sell Custom Apparel — We Handle Printing & Free Shipping

Step 3 — Create a Model with UUID Primary Key

Generate a model normally:

rails generate model Order customer_email:string total:decimal

The generated migration (with the application.rb config above) will look like:

class CreateOrders < ActiveRecord::Migration[7.1]
  def change
    create_table :orders, id: :uuid do |t|
      t.string :customer_email, null: false
      t.decimal :total, precision: 10, scale: 2
      t.timestamps
    end
  end
end

The id: :uuid option sets the column type to PostgreSQL's native UUID type with gen_random_uuid() as the default.

Association Gotcha: Foreign Keys Need UUID Type

This is the most common Rails UUID mistake. When you add a belongs_to reference in a migration, you must declare the foreign key type explicitly:

# WRONG — creates an integer foreign key
t.references :order, foreign_key: true

# CORRECT — creates a UUID foreign key
t.references :order, type: :uuid, foreign_key: true

Or when adding to an existing table:

class AddOrderToLineItems < ActiveRecord::Migration[7.1]
  def change
    add_reference :line_items, :order, type: :uuid, foreign_key: true
  end
end

If you forget the type: :uuid, Rails creates an integer order_id column and the foreign key constraint will fail to link to the UUID primary key.

The Model and ActiveRecord Queries

The Order model needs no UUID-specific code — ActiveRecord handles everything:

class Order < ApplicationRecord
  has_many :line_items
  validates :customer_email, presence: true
end
# Create
order = Order.create!(customer_email: '[email protected]', total: 49.99)
order.id  # => "550e8400-e29b-41d4-a716-446655440000"

# Find by UUID
Order.find('550e8400-e29b-41d4-a716-446655440000')

# In a controller (route: GET /orders/:id)
order = Order.find(params[:id])

Rails routes and controllers work identically whether the primary key is an integer or UUID — the only change is that params[:id] now contains a UUID string. Use the free UUID generator above to create test values for RSpec fixtures, FactoryBot factories, or Postman collections.

Generate Test UUIDs for Rails Fixtures and FactoryBot

The Cheetah UUID Generator produces RFC-compliant UUID v4 strings — copy them into RSpec fixtures, FactoryBot factories, or Rails console commands.

Open Free UUID Generator

Frequently Asked Questions

Do I need to change my model files to use UUID primary keys?

No. Once the migration sets the UUID column as primary key, ActiveRecord reads the column type from the schema and handles everything automatically. No changes to model files are needed.

Does Rails UUID work with SQLite (for development)?

Not with gen_random_uuid() — that's PostgreSQL-specific. For SQLite in development, you'd need to generate the UUID in Ruby: before_create { self.id ||= SecureRandom.uuid }. Most teams just use PostgreSQL in development to match production.

Will existing Rails routes break when switching to UUIDs?

Routes use params[:id] regardless of type — no route changes needed. Any bookmarked or cached integer-based URLs will 404 after migration since the IDs no longer exist in that format.

How do I write FactoryBot factories with UUID primary keys?

FactoryBot respects the database default, so factories work without changes. For explicit IDs: factory :order do id { SecureRandom.uuid } end.

Ryan Callahan
Ryan Callahan Lead Software Engineer

Ryan architected the client-side processing engine that powers every tool on WildandFree — ensuring your files never leave your browser.

More articles by Ryan →
Launch Your Own Clothing Brand — No Inventory, No Risk