Skip to content

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