Claude-elixir-phoenix phx:perf
Analyze Elixir/Phoenix performance — N+1 queries, assign bloat, ecto optimization, genserver bottlenecks. Use when slowness, timeouts, or high memory reported.
git clone https://github.com/oliver-kriska/claude-elixir-phoenix
T=$(mktemp -d) && git clone --depth=1 https://github.com/oliver-kriska/claude-elixir-phoenix "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/elixir-phoenix/skills/perf" ~/.claude/skills/oliver-kriska-claude-elixir-phoenix-phx-perf && rm -rf "$T"
plugins/elixir-phoenix/skills/perf/SKILL.mdPerformance Analysis
Analyze code for performance issues across Ecto, LiveView, and OTP layers. Prioritize findings by impact and effort.
Usage
/phx:perf # Analyze full project /phx:perf lib/my_app/accounts.ex # Analyze specific module /phx:perf --focus ecto # Ecto queries only /phx:perf --focus liveview # LiveView memory only /phx:perf --focus otp # OTP bottlenecks only
Arguments
$ARGUMENTS = Optional module/context path and --focus flag.
Iron Laws
- MEASURE BEFORE OPTIMIZING — Never optimize without evidence of a problem
- DATABASE FIRST — 90% of Elixir performance issues are query-related
- ONE CHANGE AT A TIME — Isolate optimizations to measure impact
- NEVER benchmark in dev mode — Always use
for performance measurements; dev mode includes code reloading, debug logging, and unoptimized compilation that invalidate resultsMIX_ENV=prod
Workflow
Step 1: Identify Scope
Check specific file if provided. Otherwise scan full project:
# Find hot paths: contexts, LiveViews, workers find lib/ -name "*.ex" | head -50
Step 2: Run Analysis Tracks
Spawn analysis agents in parallel based on focus:
Ecto Track (default or
--focus ecto):
Spawn
elixir-phoenix:elixir-reviewer with prompt:
"Analyze for N+1 queries, missing preloads, unindexed queries,
and inefficient patterns. Check: Repo.all in loops,
Enum.map with Repo calls, missing preload, queries without
indexes on WHERE/JOIN columns."
LiveView Track (default or
--focus liveview):
Spawn
elixir-phoenix:elixir-reviewer with prompt:
"Analyze LiveViews for memory issues: large assigns, missing
streams for lists, assigns that grow unbounded, heavy
handle_info processing, missing assign_async for slow ops."
OTP Track (only with
--focus otp):
Spawn
elixir-phoenix:otp-advisor with prompt:
"Analyze for OTP bottlenecks: GenServer mailbox growth,
synchronous calls in hot paths, missing Task.async for
parallel work, ETS opportunities for read-heavy state."
Step 3: Prioritize Findings
Score each finding on a 2x2 matrix:
| Low Effort | High Effort | |
|---|---|---|
| High Impact | DO FIRST | PLAN |
| Low Impact | QUICK WIN | SKIP |
High impact = affects response time, memory per user, or query count. Low effort = single file change, no migration needed.
Step 4: Present Top 5
Present findings sorted by priority:
## Performance Analysis: {scope} ### 1. {Finding} — DO FIRST **Impact**: {what improves} **Location**: {file}:{line} **Current**: {problematic pattern} **Fix**: {optimized pattern} **Estimated gain**: {e.g., "eliminates N+1, reduces queries from O(n) to O(1)"} ### 2. {Finding} — PLAN ...
Step 5: Offer Next Steps
Always end with actionable next steps — findings without follow-up get lost. Present options based on severity:
How would you like to proceed? - `/phx:plan` — Create a plan from these findings (recommended for 3+ fixes) - `/phx:quick` — Apply top priority fix directly (1-2 simple fixes) - `/phx:investigate` — Deep-dive into a specific finding
Tidewave Integration
If Tidewave MCP is available:
- Use
to runmcp__tidewave__project_eval
on suspicious queriesRepo.query!("EXPLAIN ANALYZE ...") - Use
to checkmcp__tidewave__project_eval
for GenServer bottlenecksProcess.info(pid, :message_queue_len) - Use
to check missing indexesmcp__tidewave__execute_sql_query
References
— Benchee patterns, profiling, flame graphs${CLAUDE_SKILL_DIR}/references/benchmarking.md