A performance audit across database, memory, and frontend — with numbers.
A Rails engine growing fast, needing an external eye on performance
Avo is one of the most popular Ruby on Rails admin panel engines. As their user base grew, the team wanted an independent performance review — someone to systematically read every layer of the stack and find what they'd missed.
This is what a deep performance audit looks like — not a list of suggestions, but a systematic read of every layer of the stack.
Being a library rather than an application adds constraints. General database optimizations are up to the host app. The audit surface is narrower — which makes depth matter more.
At a glance
- Client
- Avo
- Type
- Performance audit
- Areas
- Database / Memory / Frontend
- Key result
- Response times nearly halved
- Lighthouse
- 81 → 98
N+1 queries hiding behind admin panel routes
Index pages are the usual suspects. The /users, /posts, and /projects routes were inspected for N+1 queries. Avo already had a solid setup for dealing with these — but a closer look revealed two patterns worth fixing.
First: Active Storage attachments. Displaying them on index pages triggered N+1 queries on the associated Attachment and Blob models. The fix used Rails' built-in eager loading scopes — but in a generic admin engine, applying them correctly takes care.
Second: show routes with unloaded associations. A few pages triggered additional queries for related records that should have been eager loaded from the start.
Posts index — before vs. after Active Storage eager loading

Post show — before vs. after association eager loading

Allocations that multiplied on every request
For a Rails engine, memory discipline matters — every allocation you add is inherited by every host app. Profiling the more complex resources revealed two patterns worth fixing.
file_hash memoization
A method that read the entire resource file from disk on every request, just to calculate a cache hash. Memoizing the file contents (which don’t change during a deployment) cut the cost immediately.
class_name caching
A metaprogramming accessor recomputed on every call. Memoizing it produced the single biggest improvement in the audit.
Lighthouse 81 → 98
The frontend is where a Rails engine has the most control — decoupled from whatever caching or CDN the host app provides. Lighthouse scans (run through an ngrok tunnel for realistic latency) flagged image handling as the main opportunity.
Two changes made the difference: lazy loading off-screen images while preserving aspect ratios to avoid layout shift, and preloading the hero image so it renders on first paint.
The result: a 17-point jump in the Lighthouse performance score.
Before — Lighthouse performance score: 81

After — Lighthouse performance score: 98

Nearly halved mean response times
With database and memory optimizations combined, mean response times for index routes dropped by almost half. The distribution also tightened — fewer outliers, more consistent performance under load.
Response times — green: mean, yellow: p95. Index route mean nearly halved.

Combined impact of database and memory optimizations. Note the tighter, lower response times at the right margin.

“Julian is exemplary in going deep in the code to find the inefficiencies we overlooked. The fact that Avo is a library where the users have so much control makes this task even more challenging but we are grateful to have him review every aspect of it.”
See what an audit can find in your codebase.
A 30-minute intro call to understand your codebase and see if we're a good fit. No pitch, no pressure.