Once is an Ecto type for locally unique 64-bits IDs generated by multiple Elixir nodes. Locally unique IDs make it easier to keep things separated, simplify caching and simplify inserting related things (because you don't have to wait for the database to return the ID). A Once can be generated in multiple ways:
- counter (default): really fast to generate, predictable, works well with b-tree indexes
- encrypted: unique and unpredictable, like a UUIDv4
- sortable: time-sortable like a Snowflake ID
A Once can look however you want, and can be stored in multiple ways as well. By default, in Elixir it's a url64-encoded 11-char string, and in the database it's a signed bigint. By using the :ex_format
and :db_format
options, you can choose both the Elixir and storage format out of t:format/0
. You can pick any combination and use to_format/2
to transform them as you wish!
Because a Once fits into an SQL bigint, they use little space and keep indexes small and fast. Because of their structure they have counter-like data locality, which helps your indexes perform well, unlike UUIDv4s. If you don't care about that and want unpredictable IDs, you can use encrypted IDs that seem random and are still unique.
The actual values are generated by NoNoncense
, which performs incredibly well, hitting rates of tens of millions of nonces per second, and it also helps you to safeguard the uniqueness guarantees.
The library has only Ecto
and its sibling NoNoncense
as dependencies.
The package is hosted on hex.pm and can be installed by adding :once
to your list of dependencies in mix.exs
:
def deps do
[
{:once, "~> 0.0.1"}
]
end
Documentation can be found on hexdocs.pm.
To get going, you need to set up a NoNoncense
instance to generate the base unique values. Follow its documentation to do so. Once
expects an instance with its own module name by default, like so:
# application.ex (read the NoNoncense docs!)
machine_id = NoNoncense.MachineId.id!(opts)
NoNoncense.init(name: Once, machine_id: machine_id)
In your Ecto
schemas, you can then use the type:
schema "things" do
field :id, Once
end
And that's it! Be sure to look at hexdocs.pm for options and additional info.