Setting up Fastly CDN
Fastly—CDN emphasizing instant cache invalidation (< 150 ms across network) and programmable edge logic via VCL and Compute@Edge (WASM). Use when needing full control over caching logic or instant content updates.
Key differences
| Capability | Fastly | Cloudflare | CloudFront |
|---|---|---|---|
| Cache invalidation | < 150 ms | 1-30 s | 1-5 min |
| Edge programming | VCL + WASM | Workers (JS) | Functions (JS) |
| Tag-based invalidation | Yes | No | No |
| Real-time logs | Yes | Yes | Via S3 |
Terraform setup
resource "fastly_service_vcl" "main" {
name = "example-production"
domain {
name = "example.ru"
}
backend {
address = "origin.example.ru"
name = "origin"
port = 443
use_ssl = true
}
gzip {
name = "gzip-policy"
content_types = ["text/html", "text/css", "application/javascript"]
}
logging_s3 {
name = "s3-logs"
bucket_name = "fastly-logs"
path = "/cdn/%Y/%m/%d/"
}
}
VCL—custom caching logic
sub vcl_recv {
// Remove marketing params from cache key
set req.url = regsubreplace(req.url,
"\?(.*&)?(utm_source|utm_medium|fbclid|gclid)=[^&]*(&|$)",
"?"
);
if (req.http.Cookie ~ "laravel_session") {
return(pass);
}
if (req.url ~ "^/(admin|api)/") {
return(pass);
}
}
sub vcl_backend_response {
if (bereq.url ~ "\.(js|css|woff2)$") {
set beresp.ttl = 365d;
}
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 5m;
set beresp.grace = 1h;
}
}
Surrogate-Key—tagged invalidation
// Laravel: add tags to responses
public function show(Product $product): Response {
$response = response()->view('products.show', compact('product'));
return $response->header(
'Surrogate-Key',
"product:{$product->id} category:{$product->category_id}"
);
}
// On product update—invalidate only related pages
Http::withHeaders(['Fastly-Key' => config('services.fastly.api_key')])
->post("https://api.fastly.com/service/{$serviceId}/purge/product:{$product->id}");
Setup time: 2-3 days for basic config with VCL and tagged invalidation.







