Harnessing Client-Side Caching in Rails: The Power of `expires_in`
In your journey as a software developer, you’ll encounter myriad tools and techniques designed to optimize and streamline web applications. One such tool, often overlooked, is client-side caching. As backend and full-stack engineers, we spend hours crafting complex caching layers on the backend. However, we often overlook the most effective caching technique: having the request never reach the backend! Let’s delve into how requests get cached on the client using the
Cache Control Header
At the core of client-side caching is the HTTP
Cache-Control header. This header offers directives to browsers (and other caching agents) about how they should cache the content and when to consider it stale.
The most common directives include:
- max-age: Specifies the number of seconds the response remains fresh.
- no-cache: Directs caching agents to revalidate with the server before using the cached version.
publicmeans that any cache, including CDNs, can store the response.
privateensures the response is user-specific and only cached at the end-user level.
By setting the appropriate cache control headers, developers can steer the caching behavior of browsers and intermediaries, thereby optimizing both server load and user experience.
expires_in in Controller Actions
In the Rails ecosystem, the
expires_in method is our key to effortlessly managing the cache control header. Within the context of Rails actions, using
expires_in sets the
Cache-Control header on the HTTP response.
Take, for instance, an application like Designer Discount Club I’m currently building. The product data updates roughly once a day, and constructing the response requires complex queries and interactions with multiple services. Below, the
display_cards action powers an infinite scroll list on the client. By implementing
expires_in 1.hour, public: true, we essentially direct clients to retain and reuse their cached response for an hour. When users navigate back and forth, adding this cache control header reduces ~100ms round trip time from the client's perspective and diminishes request volume to our backend Redis cache by over 60%.