Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Generating UUIDs in Ruby

On this page
  1. Quick start
  2. v7 with the uuidv7 gem
  3. Rails / ActiveRecord
  4. Sequel
  5. JSON serialization
  6. Sidekiq job arguments
  7. Validation
  8. Comparing UUIDs
  9. Bytes for binary storage
  10. Performance
  11. Common pitfalls
  12. Cheat sheet
  13. Try the tools

Ruby has UUID v4 in the standard library via SecureRandom. For v7 and other versions, several small gems exist.

Quick start

require "securerandom"

SecureRandom.uuid
# => "0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b"

SecureRandom.uuid returns a string. Ruby has no built-in UUID type — strings are the convention. Generation uses the platform CSPRNG (/dev/urandom on Unix, BCryptGenRandom on Windows).

v7 with the uuidv7 gem

# Gemfile
gem "uuidv7"
require "uuidv7"

UUIDv7.generate
# => "01928a47-3b30-7c5e-9d1a-f0b8c4a7e923"

Tiny gem, no dependencies, ~50 lines of code. Generates v7 UUIDs with same-millisecond monotonic sequencing.

For other versions (v1, v3, v5), the uuid gem covers them, though it’s less actively maintained than its alternatives.

Rails / ActiveRecord

PostgreSQL:

# config/application.rb (Rails 7+)
config.generators do |g|
  g.orm :active_record, primary_key_type: :uuid
end
class CreateUsers < ActiveRecord::Migration[7.2]
  def change
    create_table :users, id: :uuid do |t|
      t.string :email, null: false, index: { unique: true }
      t.timestamps
    end
  end
end

This uses Postgres’s gen_random_uuid() as the default — v4. For v7 in Rails:

create_table :users, id: false do |t|
  t.uuid :id, primary_key: true, default: -> { "uuidv7()" } # PG 18+
  t.string :email
end

Or generate in Ruby for cross-database compatibility:

class User < ApplicationRecord
  before_create -> { self.id ||= UUIDv7.generate }
end

Sequel

DB.create_table :users do
  primary_key :id, :uuid, default: Sequel.function(:gen_random_uuid)
  String :email, null: false, unique: true
end

Same pattern as ActiveRecord — let the database generate the default, or do it in Ruby for v7.

JSON serialization

UUIDs are strings in Ruby, so they serialize to JSON strings without any special configuration:

require "json"
user = { id: SecureRandom.uuid, email: "alice@example.com" }
user.to_json
# => "{\"id\":\"0e6f1b8c-...\",\"email\":\"alice@example.com\"}"

Sidekiq job arguments

UUIDs in job arguments serialize via to_json. Sidekiq supports them out of the box:

class SendWelcomeEmail
  include Sidekiq::Job

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end

SendWelcomeEmail.perform_async(SecureRandom.uuid)

Validation

UUID_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i

def valid_uuid?(s)
  UUID_REGEX.match?(s)
end

For Rails parameter validation:

class UserController < ApplicationController
  def show
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    head :not_found
  end
end

ActiveRecord’s find raises on invalid UUID format too, so a 404 covers both “not found” and “malformed” gracefully.

Comparing UUIDs

UUIDs are strings, so == works:

a = SecureRandom.uuid
b = a.dup
a == b   # => true
a.eql?(b) # => true

For case-insensitive comparison (rare — most generators emit lowercase):

a.downcase == b.downcase

Bytes for binary storage

require "securerandom"

uuid = SecureRandom.uuid                  # canonical
hex  = uuid.delete("-")                   # 32 hex chars
bytes = [hex].pack("H*")                  # 16 raw bytes

For PostgreSQL with the pg gem, the native uuid type accepts strings directly — no manual byte conversion needed.

For MySQL with BINARY(16), convert in Ruby:

ActiveRecord::Base.connection.execute(
  "INSERT INTO users (id, email) VALUES (UUID_TO_BIN(?), ?)",
  uuid, email
)

Performance

SecureRandom.uuid is fine for typical web throughput (~500K UUIDs/sec on a modern Ruby). If you’re generating UUIDs in a tight loop, the securerandom gem from MRI is slower than native libraries — but it’s almost never a bottleneck.

For really high-throughput generation, drop into FFI with the C uuid library, or batch via SecureRandom.bytes(16 * count) and set version/variant bits manually.

Common pitfalls

Cheat sheet

GoalCode
Random UUIDSecureRandom.uuid
Time-ordered (v7)UUIDv7.generate
ValidateUUID_REGEX.match?(s)
Rails id columnt.uuid :id, primary_key: true
Bytes for binary storage[uuid.delete('-')].pack('H*')

Try the tools