To be fair there actually are quite a few DB features (mostly constraint-related) which raise by default unless you have the right validations in your changeset. It is actually covered in the docs here, but if you’re unfamiliar with Ecto and you try to work with constraints it’s easy to get the impression that the exceptions are meant to be handled.
One thing I like about the new (to Ecto) Repo.transact is that, combined with a with, it encourages you to handle errors functionally instead of using exceptions/rollbacks. Repo.transaction essentially relying on an exception/short-circuit style of error handling really wasn’t helping.
But there are some situations where exceptions are justified. For example, if you had a unique constraint for a username field you would want to handle that in the changeset so you can display helpful errors to the user. But if you had a constraint which would only be triggered by a vanishingly rare race condition, it might be a better idea to just crash on the grounds that any error handling path would essentially never be tested in practice and isn’t worth trying to maintain.


















