FrontCache compared
FrontCache composes with your CDN rather than replacing it, and it loses on several rows below. Where it differs is who decides what is cacheable: your application, in a response header, one fragment at a time.
fewer origin renders, measured on a replay of 100,000 production requests against a live app — cache on vs. off. How it was measured
Free. We tell you what share of your traffic is cacheable at the fragment level, and whether FrontCache or the cache you already have is the better tool for it.
Side by Side
Against the products a team evaluating a caching tier is most likely to name. Open-source editions where one exists.
| Capability | FrontCache | Varnish | nginx proxy_cache |
Fastly | Cloudflare |
|---|---|---|---|---|---|
| Caching model | |||||
| Page assembled from fragments | Concurrent includes | ESI, resolved serially | SSI only | ESI subset | Write it in a Worker |
| TTL per fragment | Yes | Via ESI | No | Yes | No |
| Who decides what is cacheable | Your app, in response headers; nothing is cached until it says so | Headers, overridden in VCL | Cache-Control / X-Accel-Expires | Surrogate-Control + VCL | Headers + cache rules |
| Different TTLs for crawlers and people, per fragment | bot: / guest: in the same header | Hand-written VCL | No | Not built in | Not built in |
| Invalidate by tag | By tag or URL pattern | With the xkey module | Purge is in nginx Plus; no tags | Surrogate-Key — the best there is | Cache-Tag purge, plan-dependent |
| Persistent on-disk cache | Memory + disk tiers, both free | Disk persistence is a paid edition | Disk-based | Managed service | Cache Reserve, paid |
| When the origin fails | |||||
| Behaviour on origin errors | Circuit breaker per origin call; fallback content you wrote, per URI pattern | Serves stale (grace) | Serves stale (proxy_cache_use_stale) | Serves stale (stale-if-error) | Serves stale; custom error pages |
| Deployment | |||||
| Runs inside the application process | Servlet filter (Java) | No | No | No | No |
| Self-hosted — HTML stays on your infrastructure | Yes | Yes | Yes | No | No |
| Origin language | Any that sets a header (filter mode: Java) | Any | Any | Any | Any |
| Rate limits and request rejection | Guard rules | VCL | limit_req | VCL / edge rules | Far more capable |
| Where FrontCache loses | |||||
| Global points of presence, TLS, DDoS, WAF | None — put a CDN or a front door in front | No | TLS only | Yes | Yes |
| Bot detection beyond the User-Agent | User-Agent and request rules only | Write it yourself | Write it yourself | Add-on products | Yes, and far ahead |
| Ecosystem, docs, people who already know it | Small — you talk to the people who wrote it | Large | Very large | Large | Very large |
yes · partial, paid, or manual · no. From each product’s public documentation as of October 2026. Products change — if a row is out of date, tell us and we will correct it.
Which One
Most sites that use FrontCache keep a CDN, and some keep their proxy cache too.
TLS, static assets, global points of presence, DDoS absorption and WAF. FrontCache does none of that, and is not faster than a CDN on network latency. Its number is origin offload: the renders your app no longer does.
…your pages are cacheable whole, nobody is signed in on them, and someone on the team owns the VCL or nginx config. Then the cache you have is the right one.
…one personal block makes whole pages uncacheable, crawlers are a large share of your traffic, you want caching inside a Java app without a new tier, or the rules for what is cacheable keep drifting away from the code.
<fc:include url="…"/> plays the role of
<esi:include src="…"/>. Misses are fetched in parallel, each
fragment carries its own TTL and tags, and a fragment can be included for crawlers only,
guests only, or fired asynchronously.
And if you went looking for ESI on Cloudflare: it does not process ESI. Fragment assembly there means writing and maintaining a Worker. FrontCache can sit behind Cloudflare at the origin and do the assembly there.
<!-- ESI -->
<esi:include src="/fragments/header" />
<!-- FrontCache -->
<fc:include url="/fragments/header" />
<fc:include url="/seo/footer" client="bot" />
<fc:include url="/recommendations" call="async" />
The fragment sets its own lifetime:
x-frontcache-component-maxage: 15m.
Measured, With the Method
A replay of 100,000 real production requests against a live app, run twice back to back: once with the cache on, once with it switched off. Same app, same machine, same request stream, byte-identical responses.
hobbyray.com, a site we operate. The mechanism generalizes; the exact multiplier does not.
98.7% is that replay’s working set — a hot set by construction. Over the site’s full 681k-request log the same harness measures about 66.7%. Yours will depend on your TTLs and traffic shape.
The worst case. p99 improved only 42% and the single slowest request got slower: the uncached remainder queues behind 6× the throughput. Size the origin for that fraction.
Five Minutes
Next Step
Send us an access log and we will tell you, honestly, whether fragment caching would move your numbers — or whether the cache you already run is enough.