CDN Vendor Evaluation Matrix: Scoring Providers on What Actually Matters

Two years ago I sat in a room while a retailer picked a CDN because their deck showed 310 Tbps of edge capacity and 165 PoPs. Six weeks after signing, their team was waiting 45 seconds for cache purges to propagate and couldn't get raw logs for over four hours. The problem wasn't the vendor's network — it was the evaluation sheet they'd used. It gave 25% weight to PoP count and 5% to purge speed and observability. If you've ever watched a scorecard declare a winner that your engineers didn't trust, you know exactly how that story ends.

Why Feature Checklists Give You False Confidence

Most teams start their CDN comparison with a spreadsheet that looks responsible: 60 rows of features, a simple Yes/No or 1-5 rating, and an average at the bottom. I've reviewed dozens of these sheets over the last decade, and they almost always declare a tie or favor the cheapest bidder. The issue isn't effort — it's that a binary checklist treats "supports stale-while-revalidate" as equal to "has Anycast with automated failover in your primary markets." They're not equal, and your users will feel the difference on the first traffic spike.

Back in 2019, we ran an RFP for a global video platform and made this exact mistake. Every vendor checked the boxes for HTTP/2, HTTP/3, Brotli, image optimization, and WAF. On paper, they were identical. But when we dug into how they handled cache key customization and origin shielding in Asia-Pacific, the gaps were massive. One provider only allowed cache keys based on URL, while another let us include headers, cookies, and query strings with precise control — critical for our personalized manifests. We'd have missed that if we hadn't moved beyond Yes/No scoring. If you're starting your process, your CDN RFP Template: Writing Requirements That Get Meaningful Vendor Responses needs to force vendors to explain how they do something, not just that they do it.

That's where a weighted evaluation matrix fixes things. Instead of treating every requirement as equal, you assign weights that reflect business impact and test them with evidence — not slideware. You score what you can actually measure during a trial, not what the sales engineer promises. The structure below is what I use now for every mid-market and enterprise evaluation. It's simple but it prevents popularity contests.

// Example: Weighted scoring model - weights must total 1.0
{
  "evaluation_matrix": {
    "performance": {
      "weight": 0.30,
      "criteria": {
        "p95_ttfb_global": 0.40,
        "cache_hit_ratio": 0.35,
        "origin_offload_percent": 0.25
      }
    },
    "reliability_ops": {
      "weight": 0.25,
      "criteria": {
        "purge_propagation_p95": 0.30,
        "config_deployment_time": 0.25,
        "log_delivery_delay": 0.25,
        "api_uptime_sla": 0.20
      }
    },
    "security": { "weight": 0.20 },
    "developer_experience": { "weight": 0.15 },
    "commercial": { "weight": 0.10 }
  },
  "scoring": "score = Σ (criterion_score_0_to_5 * criterion_weight) * category_weight"
}

Building Weights That Match Your Traffic, Not Their Marketing

You can't set weights in a vacuum. A media site serving 80% cacheable video has completely different priorities than a SaaS app with 70% uncacheable API calls. I always start by pulling the last 30 days of origin logs and classifying traffic: cacheable vs. dynamic, geographic distribution, and request mix. One e-commerce client I worked with discovered 62% of their origin load was just three API endpoints for cart and inventory — suddenly edge compute and origin shield architecture mattered more than raw throughput. Without that data, they'd have over-weighted PoP count and under-weighted shielding.

Get your stakeholders to argue about weights before you see any vendor demos. I run a workshop where product, engineering, SRE, and security each get 100 points to allocate across categories. Engineering might push for fast config deploys and Terraform provider maturity, while security wants WAF rule propagation under 30 seconds and detailed audit logs. When we did this for a fintech migration, the SRE team's 35-point allocation to observability completely changed our final ranking. Vendors who looked great on performance alone dropped when we scored log delay and alerting flexibility. Your CDN Proof of Concept Planning: Designing a PoC That Answers Real Questions should then test those weighted priorities — don't run a generic PoC that measures everything equally.

Keep your scale consistent and evidence-based. I use a 0-5 scale where 0 is "doesn't exist or failed test," 3 is "meets requirement with manual workarounds," and 5 is "exceeds requirement and we verified it in PoC." Every score above a 3 needs a link to a test result, HAR file, or API response. That discipline stops vendor scoring from becoming a beauty contest. The small script I use to calculate final scores also flags where vendor claims don't match PoC data, so you can address gaps before contract stage.

# weighted_score.py - Calculate provider score from PoC results
def score_provider(results):
    # results = {category: {criterion: {score, weight}}}
    total = 0.0
    for cat, cat_data in results.items():
        cat_weight = cat_data["weight"]
        cat_score = sum(
            c["score"] * c["weight"] for c in cat_data["criteria"].values()
        )
        total += cat_score * cat_weight
        print(f"{cat}: {cat_score:.2f} * {cat_weight} = {cat_score * cat_weight:.2f}")
    return round(total, 2)

# Example: Vendor A scored 4.2 on performance but 2.8 on ops
# weighted total = 3.61 vs Vendor B at 3.88 (more balanced)
# The math makes tradeoffs visible - you can't hide weak ops with strong marketing

The Five Measurement Areas Vendors Can't Spin

Marketing sheets love to highlight aggregate network capacity and number of PoPs — numbers that rarely correlate with your users' experience. What matters is how a provider performs for your specific workload, under your configuration, in your key geographies. I focus on five areas and demand real tests for each. For performance, we don't just measure average TTFB; we look at p95 and p99 TTFB from real user locations using RUM or synthetic tests from Catchpoint or ThousandEyes. The guidance in the HTTP Working Group Specifications around caching semantics and the cache-control directives is what determines whether that performance is repeatable, not just fast once. And articles from web.dev Articles on LCP and cache efficiency helped us tie CDN behavior directly to Core Web Vitals for that retailer.

Operational behavior is where you'll live day-to-day, and it's what most teams forget to score heavily. How long does a purge take to reach 99% of edge nodes? Can you deploy a config change via API in under 60 seconds and roll it back instantly? How quickly do logs arrive in your S3 bucket or Splunk — is it 5 minutes or 90 minutes? These aren't nice-to-haves; they determine your incident response time. I've seen vendors claim "instant purges" that actually took 12-18 seconds at p95 during our PoC, which broke our content update workflow. That's why we test this under load, with our actual cache keys and surrogate keys. Your final cutover plan in the Comprehensive CDN Migration Checklist: Every Step from Planning to Cutover depends on these numbers being honest, so score them before you sign.

Category Metric to Score How We Test It What Good Looks Like (0-5 Scale)
Performance p95 TTFB - Cached Synthetic + RUM from top 5 markets, cold and warm cache 5 = <45ms global p95; 3 = <90ms; 0 = >150ms
Cache Efficiency Origin Offload / Hit Ratio Measure with identical origin & cache-key config for 7 days 5 = >96% hit ratio; 3 = >88%; 0 = <75%
Operations Purge Propagation p95 50 surrogate-key purges, timed via API polling edge nodes 5 = <2s global; 3 = <8s; 0 = >20s
Observability Log Delivery Delay Time from request to log availability in SIEM/S3 5 = <60s; 3 = <5 min; 0 = >15 min or batched hourly
Reliability Config Deploy & Rollback API deploy + validation + rollback, measured 10 times 5 = <30s with version history; 3 = <

From Theory to Spreadsheet: Building a Matrix You’ll Actually Use

We’ve all seen that 200-row feature checklist vendors love to fill out. You know the one — every box is checked “yes” or “roadmap Q3,” and somehow everyone scores 98%. It’s useless. Your matrix shouldn’t have 200 rows; it should have 12 to 15 weighted criteria max, pulled directly from those five measurement areas. If you can’t tie a row to lost revenue, buffering, or an ops page at 2 a.m., cut it.

Here’s how we do it in practice: assign weights that total 100% based on *your* traffic profile. A video-heavy platform might put 35% on raw performance (TTFB, throughput) and 25% on origin shielding and cache efficiency, while a financial API might flip that and put 40% on reliability and security posture. Don’t let the vendor’s strengths dictate your weights. Score each vendor 1-5 on each criterion using hard data from your pilot, not their sales deck. Then your weighted score is brutally honest. If you haven’t set up that pilot correctly, you’ll be scoring marketing fiction — nail your CDN Pilot Testing Methodology: Metrics, Duration, and Success Criteria before you score a single cell.

Keep it simple and auditable. Anyone on your team should be able to explain why Vendor A got a 3 and Vendor B got a 5 on “cache hit ratio” without hand-waving.

// Example weighted scoring model - keep it in code, not just Excel
const evaluationMatrix = [
  { criterion: "p95 TTFB (global)", weight: 0.25, vendorA: 4, vendorB: 3 },
  { criterion: "Cache Hit Ratio", weight: 0.20, vendorA: 5, vendorB: 4 },
  { criterion: "Origin Shield Cost & Effectiveness", weight: 0.15, vendorA: 3, vendorB: 5 },
  { criterion: "WAF & DDoS Mitigation (p95 mitigation time)", weight: 0.20, vendorA: 4, vendorB: 4 },
  { criterion: "Real Support Response (sev-1)", weight: 0.10, vendorA: 2, vendorB: 5 },
  { criterion: "Contract & Egress Pricing ($/TB)", weight: 0.10, vendorA: 5, vendorB: 3 },
];

function weightedScore(vendorKey) {
  return evaluationMatrix.reduce((total, row) => {
    return total + (row[ vendorKey ] * row.weight);
  }, 0).toFixed(2);
}

// weightedScore('vendorA') => 3.95
// weightedScore('vendorB') => 3.85  // Cheaper isn't always better when support is a 2

When the Scores Don’t Match Reality: Debugging Your Evaluation

You’ve run the numbers and Vendor X wins by 0.4 points, but your gut says they’ll crumble on Black Friday. Trust your gut and dig in — that’s usually a weighting or measurement problem. The most common lie we see is PoP count. A vendor claims 300+ PoPs, but 40% of your users are in Southeast Asia and that vendor has two congested nodes in Singapore serving the entire region. We’ve measured 45-60ms deltas in p95 latency there versus a vendor with “only” 150 well-placed PoPs. Don’t score PoP count; score measured latency from your actual user locations using RUM data, not synthetic tests from their looking glass.

Another trap: pricing that looks 30% cheaper until you hit overages. That $0.035/GB headline rate often excludes origin shield, request fees, and log delivery. One “budget” vendor we tested was $0.028/GB for cache egress but charged $0.12/GB for shield fetches — and with a 82% hit ratio, our effective blended cost was $0.048/GB. You’ve got to model your *blended* cost per TB at 85%, 90%, and 95% hit ratios. And if you’re migrating under pressure, don’t underestimate the cutover risk. A vendor with a perfect score but a complex, DNS-heavy migration plan can cost you more in downtime than you’ll save in a year. Have a look at your CDN Traffic Cutover Strategy: Migrating Without Downtime or Data Loss before you award points for “easy onboarding.”

If scores are tied or feel wrong, re-run the sensitivity analysis. What happens if you shift 10% weight from pricing to performance? If the winner changes, your evaluation isn’t robust — you don’t have a clear winner, you have two different trade-offs. That’s when we recommend a dual-CDN pilot or a phased CDN DNS Migration Planning: Changing DNS Providers Without Breaking Resolution to de-risk it. And always, always call their support at 11 p.m. on a Tuesday during the trial. If it takes 45 minutes to get a human who can actually purge cache, that 5/5 they gave themselves for “24/7 expert support” is really a 2.

Frequently Asked Questions

How long should we run a pilot before scoring performance reliably?

You need at least 14 days, ideally 21, to capture a full business cycle and one traffic spike. Anything under 7 days and you're just measuring noise. We push 5-10% of production traffic (not synthetic) through each candidate and collect p50, p95, and p99 TTFB, hit ratio, and origin offload per hour. Less than that and vendors will cherry-pick their best PoP for your test.

Should cost ever be weighted more than 20%?

Almost never. If cost is your heaviest weight, you’re incentivizing a race to the bottom that you’ll pay for in buffering and outages. We cap cost at 15-20% for most clients. The exception is static asset delivery at massive scale (100+ PB/month) where a $0.005/GB difference is literally $500k. Even then, model the cost of a 0.1% drop in hit ratio — it’ll wipe out those savings in origin egress fees.

How do we score vendors who refuse a paid pilot or trial config?

That’s a score of 1, automatically. Any vendor confident in their network will let you test with real traffic and your origin. If they only offer a demo with their “optimized test origin” or a looking-glass ping, they’re hiding something. Walk away or dock them heavily on transparency and reliability. We’ve never regretted disqualifying a vendor at this stage.

Can we use this same matrix for a multi-CDN decision?

Absolutely, but change the weights. For multi-CDN, we add two criteria: “traffic steering API quality” (load balancing, failover speed) and “log/normalization consistency.” You want vendors whose real-time logs and cache-control semantics don’t fight each other. Score how fast you can shift 100% of traffic away — if it’s >90 seconds via DNS TTL, that’s not failover, that’s an outage.

Related Articles