Simple configuration for UUID primary keys in Ecto
Using UUID's as primary keys can have many benefits, and if you're using
PostgreSQL you have the advantage of solid performance and efficient
storage of those UUIDs leading to good scalability even compared to
bigint
.
With Ecto, using UUID primary keys is very easy, however most guides out there are still written for Ecto 1.x or 2.x -- in modern times using UUIDs is even easier with Ecto 3+.
In your config.exs
, simply configure your repo to use the
:binary_id
by default for primary keys and foreign keys:
config :my_app, MyApp.Repo, migration_primary_key: [name: :id, type: :binary_id], migration_foreign_key: [column: :id, type: :binary_id]
You don't have to modify your migrations at all; Ecto will use UUIDs for
keys unless you tell it otherwise, just as it was previously with
bigint
keys.
The only other required step is to annotate your schemas so they use
:binary_id
as well. You can do this on each individually, but
I generally prefer to do this in a behaviour that wraps
Ecto.Schema
. For example,
defmodule MyApp.Schema do @moduledoc """ Behaviour to replace `Ecto.Schema` to set some defaults across all schemas in the codebase -- namely, UUID primary keys. """ defmacro __using__(_opts) do quote do use Ecto.Schema @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id end end end
Then you can use this in your schemas:
defmodule MyApp.User do use MyApp.Schema ... end
And that's all there is to it! I hope this helped you avoid setting
primary_key: false
in every migration you write.