Website Optimization (3): Caching Strategy (CDN / Static-Dynamic Splitting / Cache-Control)

The last post covered buying and configuring the server. This one is about caching strategy — not just the Redis cache inside the application, but also caches at external cloud services like a CDN. Use caching well and your site opens instantly.

This is part of an ongoing series. Based on Renfei’s Blog 2020 Major Update, I’m covering each area separately: region selection, cloud server configuration, environment setup (JVM), caching strategy, Spring Boot configuration, and front-end page optimization.

Note: this is my personal experience, not a professional benchmark. Some of it isn’t rigorous — please bear with me.

The last post covered buying and configuring the server. This one is about caching strategy — not just the Redis cache inside the application, but also caches at external cloud services like a CDN. Use caching well and your site opens instantly.

Caching Inside the Site

The idea behind in-site caching is simple. Large sites split database reads and writes precisely because the overwhelming majority of requests are reads and writes are rare. Looking at my own blog’s usage, roughly 99% of requests fetch content; only a tiny fraction are comment writes or log records. And the data being queried rarely changes — an article doesn’t get rewritten often — so there’s no need to hit the database every time. Cache hot data in memory and serve it from there on the next query.

My program is a fairly classic three-tier architecture: presentation layer (UI), business logic layer (BLL), and data access layer (DAL). I put the cache in the business logic layer — the service layer — keyed on package name, method name, and parameters. If cached data exists, it’s returned straight to the presentation layer without running business logic or querying the database, which massively improves response time. If there’s no cache, it queries the database and caches the result. Easy to follow.

Static-Dynamic Splitting

I implemented static-dynamic splitting years ago. Back then it was called an image host; now it’s called a CDN. Put plainly: hand images, JS, CSS, and other static files to someone else, relieving the network pressure on your own server while using their distribution network to deliver files to data centers across the country so users fetch static files from nearby nodes.

My approach is to use Alibaba Cloud’s OSS object storage to hold static files, which guarantees they won’t be lost — before this, every site migration lost a few files. Then I use a CDN to distribute those static files, so users read from nearby nodes and my own server handles less.

Full-Site CDN

Full-site CDN builds on CDN: it tells static requests apart from dynamic ones, caches the static ones, and still forwards dynamic requests to origin. I put a full-site CDN in front not for speed but for security — it completely hides my origin server’s IP, so attackers can’t scan my server directly for vulnerabilities. I’ll do a dedicated post on security later.

HTTP Response Header Cache Control

Besides controlling your own caching strategy, you can control caching on the client side. When responding to an HTTP request you can add Cache-Control to the headers to govern client caching rules:

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>

For files your application never changes, you can usually add aggressive caching before sending the response headers. This includes static files served by the application, such as images, CSS files, and JavaScript files:

Cache-Control:public, max-age=31536000

There are many ways to use Cache-Control, and I won’t go through them all. The point for webmasters is: if you need to control client-side caching rules, look up the Cache-Control response header.