Great question!
I mostly try to avoid tagging in with, because I feel it makes the code harder to understand. At VBT projects we use a credo check to prevent this pattern. Before I started working with them, the team was using this pattern extensively, and no one really misses it now ![]()
In this particular example, I’d make the core function return something like {:ok, post_with_meta} | {:error, :not_found | {:no_meta, post} | :unauthorized}, which I think clearly communicates what can go wrong with a business operation.
The client such as controller or absinthe resolver can now do something like:
case Core.fetch_post(...) do
{:ok, post_with_meta} -> ...
{:error, :not_found} -> ...
...
end
We mostly work with graphql, and we use some company-wide absinthe middleware that automatically handle common errors, such as unauthorized or Ecto.Changeset.t, which keeps the resolver code small and focused.






















