DOMAIN:NETWORKING:CDN_EDGE¶
OWNER: karel UPDATED: 2026-03-24 SCOPE: all CDN, WAF, DDoS, and edge platform operations AGENTS: karel (primary), stef (origin DNS), rutger (origin servers), victoria (security policy), leon (deploy chain) PROVIDER: Bunny.net (BunnyCDN) TERRAFORM: bunnynet/bunnynet provider
CDN:OVERVIEW¶
PURPOSE: accelerate content delivery, protect origins, reduce origin load PROVIDER: Bunny.net (formerly BunnyCDN) PRODUCTS_USED: - Pull Zones — CDN content delivery (core) - Bunny Shield — WAF + DDoS + bot detection (security) - Stream — video delivery (future, if client needs video) - Edge Storage — push-based static hosting (for static sites) PRICING: pay-as-you-go, $0.01/GB EU, blocked traffic FREE TERRAFORM: bunnynet/bunnynet provider (IaC, version-controlled) API_KEY: Vault path admin-ui/api-keys/bunny (piotr manages)
RULE: EU-only edge locations (data sovereignty) RULE: never cache dynamic/sensitive data (auth tokens, PII, session data) RULE: all CDN changes via Terraform or Bunny API — never manual dashboard RULE: Karel manages edge, Stef manages origin DNS — clear boundary
CDN:PULL_ZONES¶
SETUP (new client project)¶
resource "bunnynet_pullzone" "client" {
name = "${var.client}-${var.project}"
origin_url = "https://${var.origin_domain}"
# EU-only edge locations (data sovereignty compliance)
# Bunny.net allows per-zone geo restriction
blocked_countries = [] # manage via WAF instead
# Performance
enable_gzip_compression = true
enable_brotli_compression = true # preferred over gzip (20-30% smaller)
# Caching
cache_control_max_age_override = -1 # respect origin Cache-Control headers
cache_error_responses = false # don't cache 5xx errors
# Security
add_canonical_header = true
enable_origin_shield = true # additional caching layer in front of origin
origin_shield_zone_code = "DE" # Frankfurt (closest to origin)
# CORS
add_cors_headers = true
# Logging
logging_enabled = true
logging_ip_anonymization_enabled = true # GDPR compliance
}
AFTER_CREATION:
1. Karel tells Stef the pull zone hostname: {pullzone}.b-cdn.net
2. Stef creates CNAME: cdn.{domain} -> {pullzone}.b-cdn.net
3. Karel verifies CDN serving content correctly
VERIFY:
TOOL: curl
RUN: curl -I https://cdn.{domain}/assets/main.js
CHECK:
→ CDN-Cache-Status: HIT (or MISS on first request)
→ Server: BunnyCDN
→ Content-Encoding: br (Brotli) or gzip
→ X-Pull-Zone: {pullzone-name}
PULL_ZONE_ARCHITECTURE¶
Client Browser
→ CDN Edge (Bunny PoP, EU)
→ Origin Shield (Frankfurt PoP)
→ Origin Server (UpCloud, de-fra1)
Cache MISS flow: Browser → Edge → Shield → Origin
Cache HIT flow: Browser → Edge (response from edge cache)
Shield HIT: Browser → Edge → Shield (response from shield cache)
CDN:CACHE_STRATEGIES¶
PER_CONTENT_TYPE¶
| Content Type | Cache-Control | CDN TTL | Rationale |
|---|---|---|---|
| Static assets (JS/CSS with hash) | public, max-age=31536000, immutable | 1 year | Filename changes on content change |
| Images (with hash) | public, max-age=31536000, immutable | 1 year | Same as above |
| Fonts | public, max-age=31536000, immutable | 1 year | Fonts rarely change |
| HTML pages | no-cache | 0 (revalidate) | Must always get fresh HTML |
| API responses | no-store | 0 (never cache) | Dynamic data, auth-dependent |
| Favicon/robots.txt | public, max-age=86400 | 24 hours | Changes rarely |
| Service worker | no-cache | 0 (revalidate) | Must always be fresh |
CACHE_CONTROL_HEADERS (set by application, not CDN)¶
RULE: application developers (floris/floor, urszula/maxim) set Cache-Control headers RULE: Karel verifies headers are correct, does NOT override at CDN level (except emergency)
CORRECT: Cache-Control: public, max-age=31536000, immutable
→ for hashed static assets (/assets/main.abc123.js)
CORRECT: Cache-Control: no-cache
→ for HTML pages (CDN revalidates with origin on every request)
CORRECT: Cache-Control: no-store
→ for API responses containing user data
WRONG: Cache-Control: public, max-age=31536000
→ for non-hashed assets (users get stale content after deploy)
WRONG: no Cache-Control header at all
→ CDN uses default behavior (unpredictable caching)
CACHE_KEY¶
DEFAULT: URL path + query string VARY: respect Vary header (Accept-Encoding, Accept-Language) RULE: never include cookies in cache key (breaks caching, leaks session data)
CDN:CACHE_PURGE¶
POST_DEPLOY_PURGE (Karel in deploy chain)¶
DEPLOY_CHAIN_POSITION:
... → Stef (network) → KAREL → Leon (cutover)
ON_DEPLOY_TRIGGER:
1. Receive notification from Leon (post-deploy)
2. Purge per-path cache (NOT full zone purge):
PER_PATH_PURGE:
TOOL: curl (Bunny.net API)
RUN: curl -X POST "https://api.bunny.net/purge?url=https://cdn.{domain}/index.html" \
-H "AccessKey: {api_key}"
RUN: curl -X POST "https://api.bunny.net/purge?url=https://cdn.{domain}/assets/*" \
-H "AccessKey: {api_key}"
FULL_ZONE_PURGE (emergency only, human approval required):
TOOL: curl
RUN: curl -X POST "https://api.bunny.net/pullzone/{zone_id}/purgeCache" \
-H "AccessKey: {api_key}"
WARNING: purges ALL cached content — causes origin load spike
VERIFY_PURGE:
TOOL: curl
RUN: curl -I https://cdn.{domain}/index.html
EXPECT: CDN-Cache-Status: MISS (first request after purge)
RUN: curl -I https://cdn.{domain}/index.html
EXPECT: CDN-Cache-Status: HIT (second request — cached again)
RULE: NEVER purge ALL zones without human approval (origin load impact) RULE: per-path purge is safe and preferred
CDN:BUNNY_SHIELD (WAF + DDoS + BOT DETECTION)¶
TIERS¶
| Tier | Price | Features |
|---|---|---|
| Basic (free) | $0 | OWASP WAF rules, basic DDoS, basic bot detection |
| Advanced | $9.50/mo/zone | Custom WAF rules, advanced DDoS, JS challenges, rate limiting |
GE_POLICY: Basic for all zones, Advanced for high-value client zones (human approval for cost)
WAF (Web Application Firewall)¶
MANAGED_RULES: OWASP Top 10 coverage (enabled by default on all pull zones) - SQL injection detection - XSS (cross-site scripting) detection - Path traversal detection - Remote code execution detection - Protocol violation detection
CUSTOM_RULES (Advanced tier): - Per-client rate limiting - Geo-blocking (country-level) - IP reputation blocking - Custom header inspection
CONFIGURATION:
resource "bunnynet_pullzone" "client" {
# ... pull zone config ...
# WAF
waf_enabled = true
waf_log_only = false # false = block, true = log only (testing)
# Rate limiting
request_limit = 200 # requests per second per IP
request_limit_cookie_domain = "" # not cookie-based
}
RULE: Karel configures what Victoria decides — Victoria defines policy, Karel implements
DDoS PROTECTION¶
CAPACITY: Bunny.net absorbs 250+ Tbps DDoS COST: blocked traffic is FREE (only clean requests billed) RESPONSE_LEVELS: 1. Always-on: volumetric attack absorption (automatic, no action needed) 2. Shield mitigation: JS challenge for suspicious traffic (enable during active attack) 3. Under-attack mode: aggressive challenge for ALL traffic (last resort)
ON_DDOS_DETECTED:
1. Karel enables Shield mitigation (immediate)
2. Karel alerts Victoria (security investigation) + Mira (incident coordination)
3. If mitigation insufficient:
→ escalate to under-attack mode
→ coordinate with Rutger to scale origin
4. Post-attack:
→ analyze attack pattern (source IPs, methods)
→ update WAF rules to prevent recurrence
→ incident report to Victoria
BOT DETECTION¶
ACTIVE: on all production pull zones ALLOWED_BOTS (white-listed for SEO): - Googlebot - Bingbot - DuckDuckBot - Yandex (if client serves CIS market) - Custom bots per client project (documented in project scope)
BLOCKED: - Known malicious bot signatures - Headless browsers without JS execution - Credential stuffing tools - Content scrapers (unless client allows)
CDN:BUNNY_STREAM (Video Delivery)¶
OVERVIEW¶
PURPOSE: video hosting and adaptive streaming (HLS) USE_WHEN: client project requires video content delivery PRICING: $0.01/GB storage + $0.01/GB bandwidth (EU)
FEATURES: - Automatic transcoding (multiple resolutions) - Adaptive bitrate streaming (HLS) - Thumbnail generation - Player embed code - Analytics (views, engagement, completion rate) - Direct upload API
DEFERRED: not currently used by any GE client — document for future reference
CDN:EDGE_STORAGE (Push Storage)¶
OVERVIEW¶
PURPOSE: static site hosting at the edge (no origin server needed) USE_WHEN: static websites, documentation sites, landing pages
FLOW: build static site → push to Edge Storage → serve directly from CDN
BENEFIT: no origin server to manage, fastest possible delivery
COST: $0.01/GB storage + $0.005/GB bandwidth (EU)
USE_WHEN: client has purely static content (HTML/CSS/JS, no SSR) DO_NOT_USE: when server-side logic is needed (API, SSR, auth)
CDN:EDGE_SCRIPTING¶
BUNNY_EDGE_SCRIPTING¶
PURPOSE: execute JavaScript at the edge (Bunny Edge Workers equivalent) USE_WHEN: request/response manipulation without touching origin
EXAMPLES: - A/B test routing (redirect X% of traffic to variant) - Header manipulation (add security headers) - URL rewriting (legacy URL redirects) - Geographic routing (serve different content by country)
// Example: add security headers at edge
export default {
async fetch(request) {
const response = await fetch(request);
const newResponse = new Response(response.body, response);
newResponse.headers.set('X-Content-Type-Options', 'nosniff');
newResponse.headers.set('X-Frame-Options', 'DENY');
newResponse.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
return newResponse;
}
}
RULE: edge scripts for infrastructure concerns only (headers, routing) — never business logic RULE: Victoria reviews all edge scripts before deployment (security implications)
CDN:MONITORING¶
WEEKLY_REPORTS (Karel)¶
METRICS_PER_CLIENT:
→ cache_hit_ratio: target >90% (measure of CDN effectiveness)
→ edge_response_time: target <50ms global average
→ bandwidth_usage: GB transferred, cost estimate
→ waf_blocked_requests: count + top block reasons
→ bot_detection: false positive/negative analysis
→ origin_load: requests that reached origin (cache misses)
CACHE_HIT_RATIO_OPTIMIZATION¶
IF: hit ratio < 90%
CHECK: are Cache-Control headers set correctly on origin?
CHECK: are query strings varying unnecessarily? (cache key pollution)
CHECK: are cookies being included in cache key? (should not be)
CHECK: is origin returning Vary header too broadly?
FIX: coordinate with frontend devs on header strategy
COST_REPORTING¶
MONTHLY: per-client bandwidth cost → Margot for invoicing
MODEL: $0.01/GB (EU)
REPORT_FORMAT:
| client | bandwidth_gb | cost_usd | cache_hit_ratio |
|---|---|---|---|
| {client} | {X} | ${X} | {X}% |
CDN:DEPLOY_CHAIN_POSITION¶
KAREL'S ROLE¶
... → Stef (DNS + TLS + firewall) →
KAREL:
1. Receive deploy trigger from Leon
2. Purge per-path cache for deployed paths
3. Verify CDN headers (MISS then HIT pattern)
4. Confirm to Leon: CDN ready, cache purged
→ Leon (cutover confirmed)
CDN:AGENT_WORKFLOW¶
FOR_KAREL¶
ON_NEW_PROJECT_CDN: 1. READ this page for CDN standards 2. CREATE pull zone via Terraform 3. ENABLE Bunny Shield (WAF + DDoS + bots) 4. CONFIGURE caching rules per content type 5. REQUEST Stef: create DNS CNAME → {pullzone}.b-cdn.net 6. VERIFY: curl headers show CDN serving content 7. HAND OFF to Leon: CDN ready
ON_DEPLOY_CHAIN: 1. RECEIVE trigger from Leon (post-deploy) 2. PURGE per-path cache (NOT full zone) 3. VERIFY: MISS then HIT pattern 4. CONFIRM to Leon: CDN ready
ON_WEEKLY_REPORTING: 1. COLLECT metrics from Bunny analytics 2. REPORT: hit ratio, response time, bandwidth, WAF blocks 3. SEND: WAF/Shield report to Victoria 4. SEND: bandwidth cost to Margot
ON_DDOS_INCIDENT: 1. ENABLE Shield mitigation immediately 2. ALERT Victoria + Mira 3. MONITOR attack pattern 4. ESCALATE if mitigation insufficient
CDN:ANTI_PATTERNS¶
BEFORE_EVERY_CDN_ACTION: 1. Am I managing origin servers? (NEVER — Arjan/Rutger's domain) 2. Am I managing origin DNS? (NEVER — Stef's domain) 3. Am I managing origin TLS? (NEVER — Stef's domain) 4. Am I caching dynamic/sensitive data? (NEVER — API no-store, auth no-store) 5. Am I using non-EU edge locations? (NEVER — data sovereignty) 6. Am I purging ALL zones without human approval? (NEVER) 7. Am I enabling paid features without human approval? (NEVER — Advanced=$9.50/mo/zone) 8. Am I defining security policy? (NEVER — Victoria defines, Karel implements) 9. Am I modifying Cache-Control headers at CDN level? (only in emergency — app sets headers)
CDN:CROSS_REFERENCES¶
DNS_MANAGEMENT: domains/networking/dns-management.md — CNAME records for pull zones TLS_CERTIFICATES: domains/networking/tls-certificates.md — edge TLS (Bunny manages) NETWORK_SECURITY: domains/networking/network-security.md — WAF integration, rate limiting DEPLOYMENT_STRATEGIES: domains/infrastructure/deployment-strategies.md — cache purge in deploy chain SECURITY: domains/security/index.md — OWASP rules, DDoS response policy PERFORMANCE: domains/performance/index.md — CDN as performance optimization