phx-perf

$npx mdskill add oliver-kriska/claude-elixir-phoenix/phx-perf

Analyzes Elixir/Phoenix performance issues across Ecto, LiveView, and OTP layers.

  • Identifies N+1 queries, assign bloat, and GenServer bottlenecks in Elixir projects.
  • Depends on Ecto, LiveView, and OTP introspection tools for analysis.
  • Prioritizes findings by impact and effort, focusing on database issues first.
  • Outputs prioritized optimization recommendations with evidence and effort estimates.

SKILL.md

.github/skills/phx-perfView on GitHub ↗
---
name: phx-perf
description: Analyze Elixir/Phoenix performance — N+1 queries, assign bloat, ecto
  optimization, genserver bottlenecks. Use when slowness, timeouts, or high memory
  reported.
---

# Performance 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

1. **MEASURE BEFORE OPTIMIZING** — Never optimize without evidence of a problem
2. **DATABASE FIRST** — 90% of Elixir performance issues are query-related
3. **ONE CHANGE AT A TIME** — Isolate optimizations to measure impact
4. **NEVER benchmark in dev mode** — Always use `MIX_ENV=prod` for performance measurements; dev mode includes code reloading, debug logging, and unoptimized compilation that invalidate results

## Workflow

### Step 1: Identify Scope

Check specific file if provided. Otherwise scan full project:

```bash
# 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:

```markdown
## 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 `mcp__tidewave__project_eval` to run `Repo.query!("EXPLAIN ANALYZE ...")` on suspicious queries
- Use `mcp__tidewave__project_eval` to check `Process.info(pid, :message_queue_len)` for GenServer bottlenecks
- Use `mcp__tidewave__execute_sql_query` to check missing indexes

## References

- `references/benchmarking.md` — Benchee patterns, profiling, flame graphs

More from oliver-kriska/claude-elixir-phoenix

SkillDescription
ash-frameworkAsh Framework — resources, actions, policies, aggregates, calculations, AshPhoenix.Form, LiveView, migrations. Use when generating resources via mix ash.codegen, editing changes, checks, types, validations, or domain code interfaces.
catchupSummarize and review what changed while you were away. Use after a weekend, vacation, or flight to check missed PRs, git commits, Linear tickets, and meetings — one prioritized brief, not a firehose.
cc-changelog|
codex-abRun an A/B codex review experiment — holistic codex review vs 3 focused dimension passes (security, ecto, liveview) on the branch diff, classify findings, report a panel-value verdict. Use when the branch is fresh, before any codex review runs.
compound-docsSearchable Elixir/Phoenix/Ecto solution documentation system with YAML frontmatter. Builds institutional knowledge from solved problems. Use when consulting past solutions before investigating new issues.
docs-check|
ecto-n1-checkDetect N+1 query anti-patterns specifically — Repo calls inside Enum/for
ecto-patternsEcto patterns — schemas, changesets, queries, migrations, Multi, associations, preloads, upserts. Use when editing Repo calls, Ecto.Query, or schema fields. Skip for Ash.
ecto:constraint-debugDebug Ecto constraint violations - trace triggers, check migrations, find duplicate data. Use when seeing unique_constraint, foreign_key_constraint, or check_constraint errors.
ecto:n1-checkDetect N+1 query anti-patterns specifically — Repo calls inside Enum/for loops, missing preloads on associations. Use when N+1 is explicitly suspected, NOT for unrelated Ecto questions or wider database performance.