Madraset El Shamamsa, Part 4: Performance, Caching, and R2 Delivery
Performance work on a content platform is mostly about avoiding unnecessary work: do not ask the browser to build an article it could receive as HTML, do not send a media request through PHP, and do not cache a private response as if it were public.
Madraset El Shamamsa applies those principles through server-rendered documents, configured response classes, versioned frontend assets, and object storage for large media. The configuration acknowledges that routes have different freshness and privacy requirements, while deployed cache behavior still needs live-header verification.
The delivery path
flowchart LR
Reader["Reader"] --> Edge["Cloudflare edge"]
Edge -->|"Cached public response"| Reader
Edge -->|"Miss or dynamic request"| PHP["PHP origin"]
PHP --> HTML["Fully rendered HTML"]
HTML --> Edge
Reader -->|"Hashed JS/CSS request"| Static["Versioned asset host"]
Static -->|"Asset response"| Reader
Reader -->|"Images, audio, video, PDFs request"| R2["Cloudflare R2"]
R2 -->|"Media response"| Reader
PHP composition means the initial response already contains the content and navigation. That reduces dependence on JavaScript for first render and discovery. Vite's hashed filenames allow built assets to be cached for a long time because a content change produces a new URL. R2 removes large binary transfers from the application server and gives media a delivery path suited to static objects.
Cache policy follows response semantics
The root .htaccess expresses an intended request classification before applying cache headers. In simplified form, the configured policy looks like this:
flowchart TB
Request["Incoming request"] --> Classify{"What kind of response is it?"}
Classify -->|"Matching static file extensions"| Immutable["Configured public, long-lived, immutable"]
Classify -->|"Pseudo-SSG reading page"| SSG["Intended short browser and long shared-edge cache"]
Classify -->|"Ordinary public HTML"| Public["Intended bounded browser and edge freshness"]
Classify -->|"Private page or private API"| Private["Configured no-store / no-cache"]
Classify -->|"Explicitly cacheable API"| API["Intended short public cache"]
"Pseudo-SSG" describes pages that are still executed by PHP but are configured as candidates for long shared caching because their rendered output is public and changes infrequently. It does not mean a separate build generated static HTML files. Whether Cloudflare serves these responses as intended must be confirmed from deployed headers and cache-status behavior.
The application also avoids session behavior on intended cacheable pages where possible. User-specific state can be requested separately after the generic document loads, but only endpoints explicitly designed for that purpose should participate. The configuration places personalized documents and state-changing routes in the private class.
The long-lived static rule matches file extensions; it does not verify that a URL is content-hashed or otherwise versioned. Later broad Cache-Control header-unset directives also make Apache rule precedence important. For both reasons, these values describe configured intent until representative production requests confirm the final browser-facing headers.
R2 is an origin separation, not a magic speed switch
Moving images, audio, video, and downloadable files to R2 separates storage and transfer concerns from PHP compute. It can reduce origin bandwidth and makes it easier to apply media-specific caching. The browser still pays for each resource, so responsive image sizing, compression, lazy loading, and request prioritization remain important.
flowchart TB
Authoring["Content and media workflow"] --> App["PHP page references stable asset URL"]
Authoring --> Bucket["R2 object storage"]
App --> Browser["Rendered HTML"]
Browser --> AssetDomain["Dedicated asset domain"]
AssetDomain --> Bucket
Bucket --> Browser
This division supports narrower cache invalidation: versioned build assets change by filename, media objects can use their own lifecycle, and page freshness can be configured without making one policy fit everything.
Measure the experience, not a screenshot
The earlier draft included a Lighthouse image and numeric targets without a reproducible current run. They have been removed. A trustworthy performance report needs the tested URL, device/network profile, build revision, run count, and date; field data should be separated from a lab audit.
The current Core Web Vitals are Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). FID is no longer the responsiveness Core Web Vital. The definitions and thresholds should be sourced from web.dev's Core Web Vitals documentation, then evaluated with both representative lab runs and real-user data when available.
For this platform, useful regression checks include:
- whether the main article content and LCP candidate appear in the initial HTML;
- whether production pages request hashed Vite assets rather than development URLs;
- whether images reserve dimensions and defer below-the-fold transfers;
- whether private responses carry no-store semantics;
- whether a pseudo-SSG request produces the intended browser and shared-cache headers.
Performance here is a set of inspectable delivery decisions, not a guaranteed score.