Skip to content
back to writing

Building an agent skill that actually reviews backend performance

Why most AI performance reviews are worthless, and how I built an open-source agent skill that enforces evidence discipline instead of manufacturing findings.

#ai-agents#performance#open-source#python#claude-code

Ask any coding agent to “review this backend for performance” and you’ll get one of two things: a generic checklist that could apply to any codebase on earth, or confident fabrication — invented p99 latencies, imagined query plans, made-up cache hit rates, and a recommendation to add Redis to a service with fourteen users.

Both fail for the same reason: no discipline about evidence, and no model of workload. A finding that can’t say what workload makes this matter and what evidence supports it is not a finding. It’s noise dressed as insight.

So I built backend-performance-review: an open-source agent skill that teaches AI coding agents how to do evidence-based performance review. Its most distinctive rule is that returning zero findings is a valid, successful result — because the alternative is an agent that manufactures problems to fill a report.

The problem with AI performance advice

The failure mode is obvious once you see it. A typical agent response to “review this for performance” looks like:

  • “Consider adding indexes to your database queries”
  • “You might want to implement caching here”
  • “Watch out for N+1 queries”
  • “This could be a bottleneck at scale”

All true in general. None connected to the code in front of it. No evidence that any of these problems actually exist. No workload model that would tell you whether they matter.

The worse version is when the agent invents specifics: “This query takes approximately 200ms at p99” — a number pulled from nowhere, stated with total confidence, and impossible to verify without actually running the system.

What the skill actually does

The methodology follows a single principle: every claim traces to evidence, or it says it can’t.

Performance principle → observed implementation → technology manifestation
  → evidence → bottleneck → impact under stated workload → recommendation → validation

The skill starts by detecting the stack from manifests, lockfiles, and infrastructure config. A Python script (stdlib-only, read-only, safe to point at any repository) scans the repo and classifies what it finds. Then it loads only the references that apply — a Postgres service never loads the document-store file.

Next, it builds a workload model. Not by guessing, but from repository evidence: load tests, autoscaling config, pool sizes, retention jobs, alert thresholds. It asks the developer up to seven questions, once. If you don’t answer, it proceeds anyway and caps its own confidence accordingly. The report states which conclusions would change if you had answered.

Evidence discipline is the whole point

Every finding carries the same structure. Two fields are unusual and deliberate:

Conditions — the workload under which this matters. This field may never be empty. “This is slow” is not a finding. “This becomes a bottleneck when the orders table exceeds ~1M rows and the endpoint is called more than 50 times per second” is a finding.

Validation — how to verify the claim, including something that would prove the finding wrong. If the skill can’t specify a falsifier, it can’t claim confidence in the finding.

ID:            PERF-001
Severity:      High
Confidence:    Medium
Priority:      P1 (derived, not chosen)

Problem:       Sequential database calls in a loop
Evidence:      src/api/orders.py:84 — one query per iteration
Conditions:    Matters when order count per request exceeds ~20
Validation:    Batch the queries, measure before/after with k6
               Falsifier: if batched version shows <10% improvement,
               the network round-trips are not the real bottleneck

Priority is derived from a severity/confidence matrix, never chosen directly. This makes rankings reproducible instead of vibes. A cheap fix gets tagged quick-win and sequenced early, but its priority stays the same — because priority measures impact, not effort.

Architecture: two rules that prevent rot

The skill ships ~60 reference files across databases, runtimes, distributed systems, and infrastructure. Two rules keep that from becoming a pile of overlapping documents:

  1. Category files never name a product. If databases/relational.md mentions PostgreSQL, it’s leaking. Category-level reasoning must be technology-agnostic.

  2. Technology files contain only what their category file doesn’t give you. If technology/postgres.md explains what an index is, it’s wrong — that’s in databases/relational.md. The technology file covers pg_stat_statements, partial indexes, TOAST behavior, and other things you can’t derive from relational theory alone.

This means adding support for a new database requires exactly one file and one registry entry. No changes to the methodology, no changes to SKILL.md.

- signal: cockroachdb
  kind: datastore
  category: relational
  match: [cockroach, cockroachdb]
  load: [databases/universal.md, databases/relational.md, technology/cockroachdb.md]
  tier: deep

Thirteen engines deep, everything else graceful

Support is tiered honestly. Deep means a dedicated reference file with engine-specific failure modes, diagnostics, and config trade-offs. Conceptual means the category principles apply but there’s no engine-specific file yet. Generic means universal methodology only.

The deep tier currently covers PostgreSQL, MongoDB, MySQL/MariaDB, DynamoDB, Redis, Kafka, RabbitMQ, Node.js, Python, JVM, Go, .NET, and Rust.

An unrecognized technology isn’t a failure. The skill classifies it by category, applies universal principles, and states plainly what it can’t determine. The report’s scope section always says what tier each detected component is at, so you know exactly where the analysis is strong and where it’s operating from first principles.

Tested against real code, not hypotheticals

The skill has been evaluated against four unmodified public repositories. Round 1 found three genuine bugs in the detection tooling — none of which the architecture self-check could have caught, because that check verifies internal consistency, not real-world accuracy.

An independent blind pass — agents with no memory of the project’s own findings — was then run against all four repositories. In every run, it reproduced or exceeded the original review’s primary finding. In three of four, it found real evidence the manual review had missed, including a hard SyntaxError that made one application fail to import entirely.

The false-positive rate matters more than the true-positive rate for a tool like this. A generic linter that flags everything is easy to build and useless to read. The skill is designed to produce fewer findings with more behind each one.

Works with any coding agent

The methodology is vendor-neutral Markdown. The YAML frontmatter is Claude-specific and ignored elsewhere.

# Claude Code — as a plugin
/plugin marketplace add Sanoy24/backend-performance-review

# Or copy the skill directory for any agent
cp -r skills/backend-performance-review .claude/skills/   # Claude Code / OpenCode
cp -r skills/backend-performance-review .agents/skills/   # Antigravity / Codex CLI

Once installed, just ask naturally: “Review this service for performance problems”, “Why is the /orders endpoint slow?”, or “Will this scale to 10x traffic?”

What it doesn’t do

It doesn’t modify code, run anything against production, replace a profiler or APM, or perform security review. It reads, reasons, and reports. The validation plans exist so its claims can be checked by someone who can actually run the system.

The honest limitations section in the README says this plainly: static analysis cannot measure. Without runtime evidence, most findings cap at High or Medium confidence by design. The skill can be wrong. It’s a starting point for a senior engineer, not a replacement for one.

That honesty is the point. The worst performance review tool is the one that sounds confident about everything.