A Rails plugin that provides Snowflake-like IDs for your ActiveRecord models with minimal configuration.
Snowflake IDs are 64-bit integers that contain:
- 48 bits for millisecond-level timestamp
- 16 bits for sequence data (includes hashed table name + secret salt + sequence number)
This ensures globally unique, time-sortable IDs that don't reveal the total count of records in your database.
- Transparent - Just use
t.snowflakeand it works automatically - Automatic database setup - Hooks into
db:migrateanddb:preparetasks to ensure everything is set up.
Add this line to your application's Gemfile:
gem "rails-snowflake"And then execute the installer (note the underscore):
rails generate rails_snowflake:installThat's it! Just use t.snowflake in your migrations and everything works automatically.
class CreateUsers < ActiveRecord::Migration[8.0]
def change
create_table :users, id: false do |t|
t.snowflake :id, primary_key: true # Snowflake primary key
t.string :name
t.timestamps
end
end
endNote: When using t.snowflake :id directly, Rails will complain about redefining the primary key. Always use create_table :table_name, id: false when you want a snowflake primary key.
class CreatePosts < ActiveRecord::Migration[8.0]
def change
create_table :posts do |t|
t.string :title
t.text :content
t.snowflake :uid # Additional snowflake column
t.timestamps
end
end
endYou can also use Snowflake helper in Rails generators:
# Generate a model with a snowflake field
rails generate model Post title:string uid:snowflake
# This will create a migration like:
# create_table :posts do |t|
# t.string :title
# t.snowflake :uid
# t.timestamps
# endThere's nothing else to be done at this point. t.snowflake columns will automatically get unique IDs on record creation, and they are just a :bigint column in the database.
At this point, you can use them like any other integer ID.
user = User.create!(name: "Alice")
user.id # => 115198501587747344
# Convert ID back to timestamp
Rails::Snowflake::Id.to_time(user.id)
# => 2024-12-25 10:15:42 UTC
# Generate ID for specific timestamp
Rails::Snowflake::Id.at(1.hour.ago)
# => 1766651542000012345The gem automatically hooks into these Rails tasks:
db:migratedb:schema:loaddb:structure:loaddb:seed
If you have existing models with standard Rails IDs, you'll need to run a migration to convert them to Snowflake IDs.
execute("ALTER TABLE table_name ALTER COLUMN id SET DEFAULT timestamp_id('table_name')")- Database: PostgreSQL >= 15
- Rails: 7.1+
- Ruby: 3.2+
- Function Creation: Creates a PostgreSQL
timestamp_id()function - Sequence Management: Auto-creates sequences for each table (
table_name_id_seq) - ID Generation: Uses timestamp + hashed sequence for uniqueness
- Rails Integration: Hooks into model lifecycle and database tasks
- Fork the repository
- Create your feature branch (
git checkout -b feature/my-new-feature) - Add tests for your changes
- Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin feature/my-new-feature) - Create a Pull Request
The gem is available as open source under the terms of the MIT License.
The implementation of Snowflake-like ids was initially done by Mastodon