Skip to content
Back to skills

Elixir Performance

ASecurity

Find and fix performance problems in portal/ — N+1 queries, missing preloads, unbounded lists/assigns, missing DB indexes, slow context reads. Use when a page or list is slow, the DB is hot, LiveView sockets are heavy, or before shipping a list/heavy read path.

  • 391 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
ai-agentsbashperformance

Works with

  • cursor

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add AndrewDryga/emisar --skill elixir-performance --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Elixir Performance?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Elixir Performance
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/andrewdryga-elixir-performance/badge)](https://www.skillsdirectory.com/skills/andrewdryga-elixir-performance)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: elixir-performance
description: Find and fix performance problems in portal/ — N+1 queries, missing preloads, unbounded lists/assigns, missing DB indexes, slow context reads. Use when a page or list is slow, the DB is hot, LiveView sockets are heavy, or before shipping a list/heavy read path.
effort: medium
argument-hint: "[context, LiveView, or query to profile]"
allowed-tools: Read, Grep, Glob, Bash
---

# Performance pass

Measure, then fix the cause. Don't micro-optimize what isn't hot.

## The usual suspects (emisar-specific)

1. **N+1 queries.** An association loaded per-row in a loop. Symptom: the same
   `SELECT` repeated in the log.
   - Fix: declare the association in the Query module's `preloads/0` and pass
     `:preload` to `Repo.fetch/list` (IL-10) — never `Repo.preload` inside an
     `Enum.map`. Detect: read `Enum.*` callbacks and comprehensions for context
     calls or `Repo.preload`; `rg -n 'Repo\.preload' apps/emisar/lib` lists the
     preload sites.
2. **Unbounded lists.** Loading every row, or assigning a big list to the socket.
   - Lists that can grow (runs, audit events, runners): page with `Repo.list/3`
     (keyset via `cursor_fields`), and render with **`stream/3`** in LiveView, never
     `assign(socket, :items, all)` (IL-18).
3. **Missing indexes.** Every `Query.by_*` filter, every FK, and the `not_deleted`
   soft-delete predicate should be backed by an index. Cross-check the Query helpers
   against the migration; a partial index `where deleted_at is null` matches
   `not_deleted/1`.
4. **Slow query / wrong plan.** Confirm with `Repo.explain(:all, query)` in
   `iex -S mix` (verify the call exists/shape first) — look for `Seq Scan` on a
   large table where an index should apply.
5. **Over-preloading.** The opposite problem: loading associations a screen doesn't
   use. Preload only what the caller renders.

## How to run it

```sh
cd portal
# repeated identical SELECTs in dev = N+1 (queries log by default in dev)
# profile a specific read in iex:
echo 'Emisar.Repo.explain(:all, Emisar.Runs.ActionRun.Query.all())' | iex -S mix
```
Read the LiveView's `mount`/`handle_*` for list assigns; read the context read path
for preload shape; read the migration for indexes.

## Output

Findings ordered by impact: `issue · where · cost · fix`. Fix the unambiguous ones
(add a preload to `preloads/0`, switch an assign to a stream, add a missing index in
a NEW migration when the original already ran — IL-11). Leave a judgment call (is
this list big enough to page?) as a flagged question, not a silent change. Re-measure
after fixing.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.