Skip to content

Edge Caching & Rate Limiting ​

Strum VOD relies on a multi-layer edge caching architecture designed to minimize serverless computing costs (Cloudflare Workers CPU time, Neon Postgres query compute, and Cloudflare R2 Class B read operations) while delivering sub-50ms video and metadata responses globally.

All caching, rate limiting, and HTTP cache header classification logic is centralized in the @strum-vod/edge-cache package.


1. Multi-Layer Architecture Overview ​

┌─────────────────────────────────────────────────────────────┐
│                    Browser / Video Player                   │
│   • HLS.js video buffer caching                             │
│   • Hashed static bundles cached permanently (/assets/*)    │
└──────────────────────────────┬──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│               Cloudflare CDN & Edge Tier                    │
│   • Smart Tiered Cache (Origin shielding)                   │
│   • Cloudflare Cache Rules (media.usestrum.app)             │
│   • Native Rate Limiting binding ([[ratelimits]])           │
└──────────────────────────────┬──────────────────────────────┘
                               │
               ┌───────────────┴───────────────┐
               ▼                               ▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│       Cloudflare R2          │ │     apps/api-edge (Worker)   │
│   • HLS chunks (immutable)   │ │   • caches.default           │
│   • Variant / Master .m3u8   │ │   • Proactive cachedBust     │
│   • Thumbnails / VTT / SRT   │ │   • Fallback Rate Limiter    │
└──────────────────────────────┘ └──────────────┬───────────────┘
                                                │ (Cache Miss)
                                                ▼
                                 ┌──────────────────────────────┐
                                 │        Neon Postgres         │
                                 │   • Assets, Renditions, Org  │
                                 │   • Jobs, Analytics Daily    │
                                 └──────────────────────────────┘

2. Shared Package: @strum-vod/edge-cache ​

The package @strum-vod/edge-cache (packages/edge-cache) provides three unified modules:

1. Response Cache (src/response-cache.ts) ​

Interacts directly with Cloudflare's native caches.default API:

  • Synthetic internal URIs: Uses https://strum.internal/<kind>/<id> as cache keys to avoid collision with public origin routes.
  • Fail-open: Any cache read/write issue transparently falls back to the database without throwing a 500 error.
  • Proactive invalidation: cachedBust(kind, id) removes specific cache keys upon database updates or background job completions.

Standard TTL Constants (CACHE_TTL) ​

ResourceTTLInvalidation Trigger
PLAYBACK24 hours (86400s)Asset metadata update, thumbnail change, transcode completion
HIGHLIGHTS1 hour (3600s)Highlight rendering completion, title/description edits
COMMENTS15 seconds (15s)New comment posted (absorbs viral comment storms)
SETTINGS5 minutes (300s)Organization settings / branding updates
ANALYTICS_HOURLY5 minutes (300s)Hourly cron aggregation
ANALYTICS_DAILY30 minutes (1800s)Daily cron aggregation

2. Rate Limiting (src/rate-limit.ts) ​

Eliminates external Redis KV clusters:

  • Production: Uses Cloudflare's native RATE_LIMITER binding (c.env.RATE_LIMITER.limit({ key })).
  • Local Dev / Fallback: Automatically switches to an in-memory sliding window algorithm per isolate with automatic key pruning to prevent memory growth.

3. Media Headers & Cache-Control (src/headers.ts) ​

Enforces uniform HTTP headers across API endpoints, S3 presigned URLs, and transcode workers:

File Type / PatternMIME Content-TypeCache-Control Policy
HLS Video Segments (.ts, .m4s)video/mp2t, video/iso.segmentpublic, max-age=31536000, immutable
Direct MP4 Download (download.mp4)video/mp4public, max-age=31536000, immutable
Variant Playlist (index.m3u8)application/vnd.apple.mpegurlpublic, max-age=86400
Master Playlist (master.m3u8)application/vnd.apple.mpegurlno-cache, must-revalidate
Thumbnails (.jpg, .png, .webp)image/jpeg, image/png, image/webppublic, max-age=604800 (7 days)
Subtitles & AI metadata (.vtt, .srt, .json)text/vtt, application/x-subrip, application/jsonpublic, max-age=3600 (1 hour)
Raw Source Video (sources/*)video/*private, no-store
Static Frontend Bundles (/assets/*, /_astro/*)application/javascript, text/css, etc.public, max-age=31536000, immutable
Root HTML Documents (/*)text/htmlpublic, max-age=0, must-revalidate

3. Configuring Cloudflare Cache Rules ​

To ensure Cloudflare respects these headers and maximizes cache hit ratio on the media domain (media.usestrum.app):

Run the automated setup script:

bash
export CLOUDFLARE_API_TOKEN="your_token_with_zone_rulesets_edit"
export CLOUDFLARE_ZONE_ID="your_zone_id"
./scripts/setup-cloudflare-cache-rules.sh

This script:

  1. Enables Smart Tiered Cache for topology optimization (shielding R2 from redundant origin hits across global datacenters).
  2. Deploys HTTP Request Cache Rules to force 1-year immutable caching for video segments and bypass caching for master.m3u8.

STRUM Proprietary License — © 2026 Strum. All rights reserved.