performance

Response compression (only when it helps)

Compression can dramatically reduce payload sizes for JSON and HTML, but it also costs CPU. I enable it with sane defaults and avoid compressing already-compressed content (like images). Compression can also hurt streaming responses and SSE, so I disa

N+1 Proof Serialization with preloaded associations

When rendering JSON, the serializer layer can silently trigger extra queries. Force “preload then serialize” so your JSON rendering path is deterministic. This pattern scales well in Rails APIs.

Memory-Safe “top tags” aggregation with pluck + group

Tagging systems can be expensive. For quick “top tags” features, compute from the join table with group and count. Avoid loading full taggable records.

Query plan caching and prepared statements

Query plan caching improves performance by reusing execution plans. I use prepared statements to parse once, execute many times. PostgreSQL caches plans after 5 executions. Plan invalidation occurs when statistics change. Generic plans vs custom plans

Lock-Free Read Pattern for Hot Counters (Approximate)

Sometimes exact counters aren’t worth the write cost. For high-traffic views, track increments in Redis and periodically aggregate into the DB. It’s an operational tradeoff that can dramatically reduce DB pressure.

Postgres connection pooling with pg + max lifetime

After getting burned by long-lived connections that slowly accumulate bad state (or get killed by the network) and then explode during peak traffic, I got strict about pg pooling. I keep the pool size small per instance and scale horizontally instead

N+1 prevention with includes and preload

Eager loading associations with includes, preload, or eager_load is essential for avoiding N+1 queries that kill performance. When rendering a list of posts with their authors, Post.includes(:author) loads all authors in a second query rather than fir

“Write Amplification” Guard: Only Update Changed Columns

Avoid writing rows when nothing changed—especially in batch jobs. Check changed? or compute the would-be update and skip if identical. This reduces bloat and autovacuum pressure.

const and const fn for compile-time evaluation

const defines compile-time constants, and const fn are functions that can run at compile time. I use const for magic numbers, lookup tables, and configuration that never changes. const fn is powerful for building complex constants (like hash maps or a

Fragment caching inside Turbo Frames (fast lists)

Hotwire doesn’t replace caching—it makes it more valuable because you’re sending HTML frequently. I use fragment caching inside list partials and keep cache keys stable with cache blocks. The pattern is: cache each row by record, and cache the list wr

Frontend: skeleton loading instead of spinners

Spinners hide layout shifts and make an app feel slow even when it isn’t. Skeletons preserve layout and give users a sense of progress without jumping content around. I keep skeleton components simple and match the shape of the final UI. One practical

Web Vitals reporting to an API endpoint

Synthetic performance tests don’t always match what real users experience. Web Vitals reporting gives you field data (CLS, LCP, INP, etc.). I collect vitals on the client and POST them to a lightweight endpoint, then aggregate on the backend. Sampling