Using UUIDs With Postgres in Phoenix and Ecto

Setting up Ecto to use UUIDs instead of the regular integer serial IDs with PostgreSQL in Phoenix has always been a hassle, as evident from the numerous blog posts and Stackoverflow questions (1, 2, 3, …). But as of Ecto v2 and Phoenix v1.1, you can pass --binary-id when creating a new Phoenix project to automatically use UUIDs (or other binary IDs when using different databases and adapters).

When creating a new project with --binary-id, it will automatically set appropriate values for @primary_key and @foreign_key_type in your web/web.ex. For Postgres, this means using Ecto.UUID at the back (Ecto handles this automatically):

1
2
3
4
5
6
7
8
9
10
11
12
def model do
  quote do
    use Ecto.Schema

    import Ecto
    import Ecto.Changeset
    import Ecto.Query

    @primary_key {:id, :binary_id, autogenerate: true}
    @foreign_key_type :binary_id
  end
end

Existing Applications

If you want to start using UUIDs in your existing Phoenix application, you need to specify :binary_id in your Ecto migration in addition to the model method above in web/web.ex:

1
2
3
create table(:posts, primary_key: false) do
  add :id, :binary_id, primary_key: true
end

For a more detailed solution for existing Phoenix apps, see the Ecto Schema Docs or José’s answer on Stackoverflow.