Skip to content

bunny.net — Edge

OWNER: karel
ALSO_USED_BY: stef (DNS/certs)
LAST_VERIFIED: 2026-03-26
GE_STACK_VERSION: bunnynet Terraform provider (BunnyWay/bunnynet) latest


Overview

bunny.net edge capabilities: Edge Scripting for compute@edge,
Edge Storage for globally replicated file storage, and Bunny DNS
for authoritative DNS with scripting. These complement the CDN
and security layers for GE client projects.


Edge Scripting

Edge Scripting runs JavaScript (Deno runtime) at bunny.net's 119+ PoPs.
Near-zero cold start. Supports WebAssembly (WASM) for Rust, C++, Go.

Use Cases in GE

Use Case Description
Request routing A/B testing, canary deployments at edge
Auth pre-check JWT validation before hitting origin
Geo-redirect Redirect users based on country
Header injection Add security/compliance headers
URL rewriting Clean URL mapping, legacy redirects

Creating an Edge Script

resource "bunnynet_compute_script" "router" {  
  name             = "ge-${var.client}-router"  
  type             = 0  # Standalone script  

  code = <<-JS  
    export default {  
      async fetch(request) {  
        const url = new URL(request.url);  
        const country = request.headers.get("cf-ipcountry") || "NL";  

        // EU-only access check  
        const euCountries = ["NL", "DE", "FR", "BE", ...];  
        if (!euCountries.includes(country)) {  
          return new Response("Access restricted to EU", { status: 403 });  
        }  

        return fetch(request);  
      }  
    }  
  JS  
}  

IF: logic is simple (header injection, redirect)
THEN: use bunny.net Edge Rules instead of Edge Scripting — lower cost

IF: logic requires computation (JWT validation, A/B routing)
THEN: use Edge Scripting

CHECK: edge scripts handle errors gracefully — never expose stack traces
CHECK: edge scripts have timeout handling — max execution 50ms
CHECK: edge scripts are deployed via Terraform, not dashboard


Edge Storage

Edge Storage provides globally replicated object storage.
Files are replicated across bunny.net's network for low-latency access.
No egress fees — ideal for static assets served via CDN.

Storage Zones

resource "bunnynet_storage_zone" "assets" {  
  name          = "ge-${var.client}-assets"  
  region        = "DE"  # Primary region (EU)  
  zone_tier     = 0     # Standard  

  replication_regions = ["NY", "LA", "SG"]  # Optional global replication  
}  

IF: client is EU-only
THEN: set region to DE or NL, skip replication
IF: client has global audience
THEN: enable replication to relevant regions

CHECK: primary region is always EU (DE or NL)
CHECK: storage zone name follows ge-{client}-{purpose} pattern

Linking Storage to CDN

resource "bunnynet_pullzone" "storage_cdn" {  
  name        = "ge-${var.client}-assets-cdn"  
  origin_url  = "https://${bunnynet_storage_zone.assets.hostname}"  
  origin_type = 2  # Storage zone origin  
}  

File Operations

Upload via HTTP API or bunny.net SDK:

# Upload file  
curl -X PUT "https://storage.bunnycdn.com/{zone}/{path}/{filename}" \  
  -H "AccessKey: ${STORAGE_API_KEY}" \  
  --data-binary @file.png  

# Delete file  
curl -X DELETE "https://storage.bunnycdn.com/{zone}/{path}/{filename}" \  
  -H "AccessKey: ${STORAGE_API_KEY}"  

CHECK: storage API key comes from Vault
CHECK: file paths are deterministic (content-hash or semantic) — never random UUIDs


Bunny DNS

bunny.net provides authoritative DNS with scripting capabilities.
GE uses Bunny DNS for client domains routed through bunny.net CDN.

DNS Zone Configuration

resource "bunnynet_dns_zone" "client" {  
  domain          = var.client_domain  
  nameserver1     = "kiki.bunny.net"  
  nameserver2     = "coco.bunny.net"  
}  

resource "bunnynet_dns_record" "app" {  
  zone_id = bunnynet_dns_zone.client.id  
  name    = "app"  
  type    = "CNAME"  
  value   = "${bunnynet_pullzone.client_project.cname}"  
  ttl     = 300  
}  

resource "bunnynet_dns_record" "root" {  
  zone_id = bunnynet_dns_zone.client.id  
  name    = ""  
  type    = "FLATTEN"  # CNAME flattening for root domain  
  value   = "${bunnynet_pullzone.client_project.cname}"  
  ttl     = 300  
}  

CHECK: DNS records managed via Terraform
CHECK: root domain uses CNAME flattening (FLATTEN type)
CHECK: TTL is 300s for records that may change, 3600s for stable records
CHECK: stef (DNS/certs) coordinates DNS changes

IF: migrating a client domain to bunny.net DNS
THEN: coordinate with stef
THEN: verify all existing records are replicated before nameserver switch
THEN: lower TTLs 24 hours before migration


DNS Scripting

Bunny DNS supports programmable DNS responses (Smart DNS):

// Example: Geo-weighted DNS  
export default {  
  async resolve(query) {  
    const geo = query.clientGeo;  
    if (geo.continent === "EU") {  
      return { records: [{ type: "A", value: "10.0.1.1" }] };  
    }  
    return { records: [{ type: "A", value: "10.0.2.1" }] };  
  }  
}  

IF: need geographic load balancing
THEN: use DNS scripting instead of external GSLB

CHECK: DNS scripts have fallback responses for errors
CHECK: DNS script latency stays under 5ms


Compute@Edge Patterns

Pattern: Auth Gate

Validate JWT at the edge before origin request:

export default {  
  async fetch(request) {  
    const token = request.headers.get("Authorization")?.replace("Bearer ", "");  
    if (!token) {  
      return new Response("Unauthorized", { status: 401 });  
    }  
    // Validate JWT (use imported crypto library)  
    // If valid, forward to origin  
    return fetch(request);  
  }  
}  

Pattern: Rate Limiting

// Use bunny.net KV store for distributed rate limiting  
export default {  
  async fetch(request, env) {  
    const ip = request.headers.get("x-forwarded-for");  
    const key = `rate:${ip}`;  
    const count = await env.KV.get(key) || 0;  
    if (count > 100) {  
      return new Response("Rate limited", { status: 429 });  
    }  
    await env.KV.put(key, count + 1, { expirationTtl: 60 });  
    return fetch(request);  
  }  
}  

Cross-References

READ_ALSO: wiki/docs/stack/bunnynet/index.md
READ_ALSO: wiki/docs/stack/bunnynet/cdn.md
READ_ALSO: wiki/docs/stack/bunnynet/security.md
READ_ALSO: wiki/docs/stack/bunnynet/pitfalls.md
READ_ALSO: wiki/docs/stack/bunnynet/checklist.md