When a client interacts with servers via APIs, there are two types of content delivered to the client: static resources and dynamic resources.
On Instagram, static resources are things like the app's logo or default profile picture, which are the same for everyone and don’t change. For example, the Instagram logo on the login page is pre-stored and served as-is. Dynamic resources, on the other hand, are personalised for each user. For example, your Instagram feed is generated based on who you follow and the posts you interact with. The server creates this feed on-demand, making it unique to you. Static resources are fast and constant, while dynamic ones are interactive and tailored to the user.
Caching the static resource
Since static resources don’t change often, the browser caches the static content for some time. This means that the next time you load instagram.com, the browser will not need to fetch the logo from the server, saving a network call.
Using the diagram above (taken from the book: Understanding Distributed Systems), we can understand the flow. Cacheable content is first looked for in the cache. If not found, a network call is made to the server.
Server informs the client whether to cache data or not
When a server responds with the required data to the client, it also informs the client in the HTTP response header whether the resource is cacheable. The header contains the time-to-live (TTL) for the resource, which specifies how long the resource should be cached.
This design has one flaw: if the resource changes on the server before the TTL of the cached resource expires, the client may continue to display the outdated resource. For instance, if the Instagram logo changed this Christmas, but the TTL was high, you might still see the old logo in your application (client) on December 26th.
Reverse Proxy as server-side HTTP caching
A reverse proxy is a proxy server between the actual server and the client. The proxy is indistinguishable from the actual server, so clients are unaware that they are communicating through an intermediary.
A typical use of a reverse proxy is caching static resources provided by the server. Because this cache is shared across all clients, it significantly reduces server load, far more effectively than individual client-side caching.
A reverse proxy serves as a middleman and offers much more functionality beyond caching. It can authenticate client requests on behalf of the server, rate-limit requests from specific IPs or users to prevent the server from being overwhelmed, and distribute requests across multiple servers, effectively balancing the load and enhancing the system's ability to handle higher traffic.
Nowadays, Content Delivery Networks (CDNs) are more popular. Rather than building out a server-side cache, we could simply leverage a CDN. We will discuss CDNs in more detail in another blog.
Conclusion
Caching optimises resource delivery, improves performance, and reduces server load. Techniques like client-side caching, reverse proxies, and CDNs ensure efficient and scalable client-server interactions.
Here are links to my previous posts, which I publish every Sunday on distributed systems:
- Building Resilient Applications: Insights into Scalability and Distributed Systems
- Understanding Server Connections in Distributed Systems
- How are your connections with web secure and integral?
- Understanding System Models in Distributed Systems
- Ping & Heartbeat in distributed systems
- How Real-Time Editing Works: Understanding Event Ordering in Distributed Systems
- High Availability for Social Media Platforms: Leader-Follower Architecture and Leader Election
- ACID Properties in Single Transactions Explained
- How is Concurrency Control Maintained to Ensure Isolation?
- Ensuring Atomicity in Modern Databases
Feel free to check them out and share your thoughts!
Top comments (0)