# Performance Audit

> Audits Hone for performance issues. Use when optimizing database queries, analyzing Rust async code, reviewing React rendering, or investigating slow operations. Use when this capability is needed.

- Skill: `tomevault-io/performance-audit` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/performance-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/performance-audit/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/performance-audit

---


# Performance Audit for Hone

## Rust Backend (hone-core, hone-server)

### Database Performance (db.rs)
- **N+1 Queries**: Watch for loops that execute queries
- **Missing Indexes**: Ensure indexes on `transactions(account_id)`, `transactions(date)`, `subscriptions(merchant)`
- **Connection Pooling**: Using r2d2, verify pool size is appropriate
- **Batch Operations**: Prefer batch inserts over individual inserts in loops

```rust
// BAD - N+1 query pattern
for account in accounts {
    let txns = get_transactions_for_account(account.id)?; // Query per account!
}

// GOOD - Single query with JOIN or IN clause
let txns = get_all_transactions_for_accounts(&account_ids)?;
```

### Async Performance (hone-server)
- **Blocking in Async**: Never use `std::thread::sleep` in async handlers
- **Database Access**: SQLite is synchronous - use `spawn_blocking` for heavy queries
- **Ollama Calls**: Ensure HTTP client reuses connections

```rust
// BAD - blocks the async runtime
async fn handler() {
    std::thread::sleep(Duration::from_secs(1)); // Blocks!
}

// GOOD - use tokio's async sleep
async fn handler() {
    tokio::time::sleep(Duration::from_secs(1)).await;
}
```

### Memory & Allocations
- Avoid `.clone()` in hot paths when references work
- Use `&str` instead of `String` for function parameters when possible
- Pre-allocate vectors with `Vec::with_capacity()` when size is known

## React Frontend (ui/)

### Rendering Performance
- **Unnecessary Re-renders**: Use React DevTools Profiler
- **Missing Keys**: List items need stable, unique keys
- **Heavy Computations**: Wrap in `useMemo` if expensive

```tsx
// BAD - recalculates on every render
const total = transactions.reduce((sum, t) => sum + t.amount, 0);

// GOOD - only recalculates when transactions change
const total = useMemo(
  () => transactions.reduce((sum, t) => sum + t.amount, 0),
  [transactions]
);
```

### Bundle Size
- Tailwind CSS tree-shakes unused styles (good)
- lucide-react supports tree-shaking (import specific icons)
- Check for accidentally importing entire libraries

### API Efficiency
- Paginate large transaction lists
- Debounce search/filter inputs
- Cache responses where appropriate

## Detection Algorithms (detect.rs)

### Zombie Detection
- Group transactions efficiently (use HashMap)
- Avoid re-scanning entire transaction history

### Price Increase Detection
- Index subscriptions by merchant for quick lookup
- Compare only recent transactions (last N months)

### Duplicate Detection
- Pre-categorize subscriptions once, not per-check

## Quick Checks

```bash
# Check for .clone() usage
rg "\.clone\(\)" crates/

# Check for blocking sleep
rg "std::thread::sleep" crates/

# Check bundle size
cd ui && npm run build && ls -la dist/assets/
```

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/heskew) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

