Edge congestion is inevitable. A flash sale, a viral video, or a bot scrape can push a PoP's egress to 95%+ in seconds. Without Quality of Service (QoS), the CDN serves requests first-come, first-served. The result: critical HTML and API calls queue behind 4K images and non-essential prefetch, spiking Largest Contentful Paint (LCP) and killing conversion.
CDN traffic shaping solves this by classifying, queuing, and scheduling traffic at the edge — before it hits the congested link or origin. Unlike traditional network QoS that operates at L3/L4, CDN QoS is application-aware. It understands content type, business priority, and user context, allowing you to reserve bandwidth for revenue-critical flows while gracefully degrading the rest.
Why QoS at the Edge Is Different
Traditional WAN QoS uses DSCP markings and strict priority queuing on routers. CDN edge QoS builds on that foundation but adds three unique capabilities:
- Content-aware classification: Rules based on URL path, content-type, cache status (HIT vs. MISS), device class, and even cookie or header values. A
/api/cartrequest can be P0 while/assets/video-loop.mp4is P3, even though both are HTTPS GETs. - Origin protection: Shaping protects not just the last mile, but your origin. By rate-limiting low-priority origin fetches (stale revalidation, image transforms), you preserve origin concurrency for critical dynamic requests.
- Client-aware adaptation: Edge nodes can downgrade quality based on network signals. For a user on 3G, the edge can deprioritize high-resolution images automatically, a concept closely tied to adaptive image optimization and modern protocol negotiation in HTTP/2, HTTP/3 and QUIC.
Without this, you rely on TCP fairness — which is fair, but not smart. TCP gives each connection an equal share. QoS gives each connection the share it deserves.
The 4-Tier Classification Framework
Most high-performing CDN deployments converge on a four-tier model. Keep it simple; more than five tiers becomes unmanageable to tune.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
| Priority | Class & Examples | Target SLA | Shaping Behavior |
|---|---|---|---|
| P0 — Critical | Blocking & Transactional: HTML document, critical CSS/JS, /api/* checkout, auth, personalization | P95 TTFB < 80ms, 0% drops | Strict priority, 40% reserved BW, no policing |
| P1 — Important | Above-the-fold: Hero images, web fonts, LCP elements, product JSON | P95 < 150ms | Weighted Fair Queuing (WFQ) weight 30, burst allowed |
| P2 — Best Effort | Deferred: Below-the-fold images, async JS, analytics, A/B scripts | P95 < 400ms | WFQ weight 20, WRED early drop at 70% queue |
| P3 — Background | Non-essential: Prefetch, prerender, video autoplay, bot/crawler, stale revalidation | Best effort | Scavenger, capped at 10% BW, policed & delayed |
Classification happens in the edge worker or VCL layer. Evaluate in order: first match wins. Place P0 rules at the top to avoid misclassification. For a deeper look at how requests reach the right PoP before classification, see our guide to load balancing algorithms.
Core Shaping Mechanisms at the Edge
Three algorithms do 90% of the work. You will configure them together, not in isolation.
1. Token Bucket for Rate Smoothing
The token bucket is the workhorse for egress shaping. Tokens are added at a fixed rate (your committed rate), and each byte sent consumes a token. Bursts are allowed up to the bucket depth, which absorbs micro-bursts without dropping. This is ideal for P1/P2 traffic where you want to smooth delivery without hard drops.
Configuration is two parameters: rate (tokens/sec) and burst (bucket size). Set burst to ~1.5x your rate for image-heavy pages to allow initial burst for above-the-fold assets.
2. Leaky Bucket for Strict Policing
Use the leaky bucket for P3 scavenger traffic. It enforces a hard ceiling: traffic that exceeds the leak rate is queued or dropped. Apply it to prefetch and bot traffic to prevent them from stealing bandwidth during peak. Unlike token bucket, it does not reward idle periods with burst credit.
3. Weighted Random Early Detection (WRED)
WRED prevents queue collapse. Instead of tail-dropping when a queue is full (which causes global TCP synchronization), WRED probabilistically drops low-priority packets as the queue fills. Configure lower thresholds for P2/P3. For example, start dropping P3 at 50% queue depth, P2 at 70%, but never drop P0 until 95%. This keeps latency low for critical flows even when the edge is saturated.
Prioritization in Practice
Effective prioritization is not just about marking traffic; it is about scheduling discipline and cache interaction.
Strict priority for P0, WFQ for the rest. Give P0 a strict priority queue with a small burst buffer (50-100ms). This guarantees HTML and API calls are always dequeued first. For P1-P3, use Weighted Fair Queuing. WFQ prevents starvation: even under heavy P1 load, P2 still gets its 20% share, so below-the-fold content eventually loads instead of timing out.
Cache status matters. A P1 image that is a cache HIT should be P0-like in scheduling — it costs nothing to serve. A P1 MISS that requires an origin fetch should be demoted to P2 until it is cached. This dynamic re-prioritization avoids origin thundering herds. Pair this with smart cache invalidation so critical assets stay hot and avoid unnecessary MISS demotion.
Align with browser priorities. Modern browsers send Priority Hints and HTTP/3 urgency signals (RFC 9218). Map u=0, i (highest urgency, incremental) to P0 and u=7 to P3. When the edge respects the same urgency the browser declares, you get end-to-end prioritization without custom logic. This is especially powerful when combined with edge computing where Workers can rewrite priorities per user segment.
Implementing Edge QoS: Code Examples
Most CDNs expose QoS via VCL, edge workers, or control-plane rules. Below are two portable patterns.
Example 1 — Cloudflare / Fastly VCL-style classification & header markingsub vcl_recv {
# P0: Critical - never shape
if (req.url ~ "^/api/(cart|checkout|auth)" || req.url ~ "^/critical-css") {
set req.http.X-QoS-Priority = "P0";
set req.http.X-QoS-Weight = "40";
}
# P1: LCP elements
elsif (req.url ~ "\.(woff2|css)$" || req.http.X-LCP-Hint == "hero") {
set req.http.X-QoS-Priority = "P1";
set req.http.X-QoS-Weight = "30";
}
# P3: Background - police aggressively
elsif (req.http.Purpose == "prefetch" || req.url ~ "prefetch" || req.http.X-Bot == "1") {
set req.http.X-QoS-Priority = "P3";
# Leaky bucket: 1 Mbps, no burst
call qos_leaky_bucket(rate=125000, burst=0);
}
else {
set req.http.X-QoS-Priority = "P2";
}
}
sub vcl_deliver {
# Map to HTTP/3 priority for client
if (req.http.X-QoS-Priority == "P0") {
set resp.http.Priority = "u=0, i";
} elsif (req.http.X-QoS-Priority == "P3") {
set resp.http.Priority = "u=7";
}
}
export default {
async fetch(req, env, ctx) {
const url = new URL(req.url);
const isImage = /\.(avif|webp|jpg)$/.test(url.pathname);
// Only shape cache MISS images to protect origin
if (isImage && req.headers.get("x-cache-status") !== "HIT") {
const bucket = env.QOS_BUCKET.get("p2-images", {
// Token bucket: 20 Mbps sustained, 30 Mbit burst
rate: 20_000_000 / 8, burst: 30_000_000 / 8
});
const { allowed, retryAfter } = await bucket.consume(req.headers.get("content-length") || 0);
if (!allowed) {
// Return stale or 429 with Retry-After for P2, never for P0
return new Response(null, {
status: 429,
headers: { "Retry-After": String(retryAfter), "X-QoS": "P2-throttled" }
});
}
}
return fetch(req);
}
}
Key detail: never return 429 for P0. For P0, queue and pace. For P3, 429 or serving stale is acceptable. For a full system view of where these workers run, refer to our CDN architecture overview.
Monitoring, Tuning, and Avoiding Starvation
QoS without observability is just hopeful queuing. Instrument per-class counters at each PoP:
- Queue depth & latency by class: P0 p95 queue wait should be <5ms. If P0 queues, your reservation is too low.
- Drop / throttle rate: P3 drops of 5-15% during peak are healthy. P1 drops >0.1% indicates WRED thresholds are too aggressive.
- Origin concurrency by class: Ensure P3 fetches never exceed 10% of origin connections. Use request coalescing for P3.
- Business correlation: Plot P0 TTFB against conversion rate. You should see QoS flatten the latency spike during traffic surges.
Tune weights quarterly. Start with 40/30/20/10 and adjust based on real traffic mix. If your site is image-heavy, shift 5% from P2 to P1. If you heavily prefetch, increase P3 policing. Always test with synthetic burst: replay a 5x traffic spike in staging and verify P0 remains flat while P3 degrades gracefully.
Common pitfall: misclassifying everything as P0. If 70% of traffic is P0, you have no QoS. Be ruthless — only blocking, transactional traffic is P0. Everything else must earn its priority.
When done right, edge QoS is invisible to users but obvious in metrics: stable LCP during peaks, fewer origin 503s, and a 20-40% reduction in P95 latency for critical flows. It turns the edge from a dumb cache into an intelligent scheduler — one that knows what to protect when the network gets tough.
Frequently Asked Questions
Policing drops or re-marks traffic that exceeds a rate limit immediately, causing retransmissions and poor user experience. Shaping buffers excess traffic in queues and smooths bursts over time using token bucket or leaky bucket algorithms, delivering more consistent throughput without packet loss. At the edge, shaping is preferred for user-facing content.
QoS ensures render-blocking resources like HTML, critical CSS, and hero images are classified as P0 and served from high-priority queues with reserved bandwidth. By deprioritizing low-value traffic like prefetch, analytics beacons, and background video, the edge reduces contention and delivers Largest Contentful Paint elements 30–50% faster under load.
Yes. While QUIC encrypts transport headers, CDNs classify at the application layer using URL patterns, content-type, and custom headers before encryption. HTTP/3 stream prioritization via the Extensible Prioritization scheme (RFC 9218) then maps directly to edge QoS queues, allowing urgency levels to align with CDN shaping policies.
Track per-class metrics: P0 queue latency and drop rate, P50/P95 time-to-first-byte by priority, cache hit ratio by class, origin offload for critical assets, and token bucket utilization. Alert when P0 queue depth exceeds 20% or when low-priority traffic starves due to incorrect weight allocation.