Use when implementing GraphQL resolvers with Absinthe. Covers resolver patterns, dataloader integration, batching, and error handling.
View on GitHubTheBushidoCollective/han
jutsu-absinthe-graphql
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-absinthe-graphql/skills/absinthe-resolvers/SKILL.md -a claude-code --skill absinthe-resolversInstallation paths:
.claude/skills/absinthe-resolvers/# Absinthe - Resolvers
Guide to implementing efficient and maintainable resolvers in Absinthe.
## Key Concepts
### Basic Resolvers
```elixir
defmodule MyApp.Resolvers.User do
alias MyApp.Accounts
def list_users(_parent, args, _resolution) do
{:ok, Accounts.list_users(args)}
end
def get_user(_parent, %{id: id}, _resolution) do
case Accounts.get_user(id) do
nil -> {:error, "User not found"}
user -> {:ok, user}
end
end
def create_user(_parent, %{input: input}, _resolution) do
case Accounts.create_user(input) do
{:ok, user} -> {:ok, user}
{:error, changeset} -> {:error, changeset}
end
end
end
```
### Resolution Context
```elixir
def current_user(_parent, _args, %{context: %{current_user: user}}) do
{:ok, user}
end
def current_user(_parent, _args, _resolution) do
{:error, "Not authenticated"}
end
```
### Dataloader Integration
```elixir
defmodule MyApp.Schema do
use Absinthe.Schema
def context(ctx) do
loader =
Dataloader.new()
|> Dataloader.add_source(MyApp.Repo, Dataloader.Ecto.new(MyApp.Repo))
Map.put(ctx, :loader, loader)
end
def plugins do
[Absinthe.Middleware.Dataloader] ++ Absinthe.Plugin.defaults()
end
end
# In type definitions
object :user do
field :posts, list_of(:post) do
resolve dataloader(MyApp.Repo)
end
end
```
### Custom Dataloader Source
```elixir
defmodule MyApp.Loaders.User do
def data() do
Dataloader.KV.new(&fetch/2)
end
defp fetch(:posts_count, user_ids) do
counts = MyApp.Posts.count_by_user_ids(user_ids)
Map.new(user_ids, fn id ->
{id, Map.get(counts, id, 0)}
end)
end
end
```
## Best Practices
1. **Use Dataloader** - Prevents N+1 queries
2. **Keep resolvers thin** - Delegate to context modules
3. **Handle errors gracefully** - Return meaningful error messages
4. **Use middleware** - For cross-cutting concerns like auth
5. **Batch related queries** - Use dataloader batching
## Middleware
```elixir