Learn
Best CDN for Video Streaming in 2026: Full Comparison with Real Performance Data
Best CDN for Video Streaming in 2026: Full Comparison with Real Performance Data If you are choosing the best CDN for ...
A single misconfigured CORS header on a DigitalOcean Spaces bucket can silently break every font and async API call your App Platform frontend makes — and the CDN will cache that broken response for 24 hours. In Q1 2026, DigitalOcean rolled out revised default TTLs and origin-response handling on their Spaces CDN edge, which means guides written before January are now subtly wrong in ways that surface only under production load. This article gives you the exact 2026 playbook: configuring the DigitalOcean Spaces CDN to serve static assets from an App Platform deployment, getting CORS right on the first pass, wiring up custom domains, handling cache invalidation, and deciding when to graduate to an external CDN. No fluff, no 101-level definitions.

Spaces pricing has stayed flat since 2024: $5/month for 250 GB storage plus 1 TB outbound transfer, $0.01/GB beyond that. The built-in CDN endpoint remains free to enable. For small-to-mid-scale workloads — marketing sites, SaaS dashboards, internal tooling with moderate asset counts — the economics are hard to argue with. What changed in 2026 is the edge behavior: DigitalOcean now respects Cache-Control headers from the origin more strictly, and the default edge TTL dropped from 24 hours to 1 hour for objects that lack explicit cache directives. If your deploy pipeline doesn't stamp assets with long-lived cache headers and content hashes, you're paying for more origin pulls than you used to.
App Platform, as of May 2026, supports static-site components, service components, and worker components. Static-site components already get a built-in CDN from DigitalOcean, but it serves the app itself — not your user-uploaded media, not your build artifacts in Spaces. That distinction is where most setup guides fall apart.
The clean architecture separates concerns. App Platform serves your application code (HTML, server-rendered pages, API routes). Spaces CDN serves everything that doesn't change per-request: images, CSS/JS bundles, video thumbnails, downloadable files. Your frontend references Spaces assets via the CDN URL — either the default subdomain (bucketname.region.cdn.digitaloceanspaces.com) or a custom domain you CNAME to it.
This means your App Platform component stays small, its build output stays lean, and your egress costs split across two billing surfaces instead of hammering one. In 2026, App Platform's Starter tier ($5/month) includes 1 GB outbound; the Basic tier ($12/month) includes 10 GB. Offloading assets to Spaces means those limits stretch significantly further.
Create the bucket in the same datacenter region as your App Platform app. As of 2026, Spaces is available in NYC3, SFO3, AMS3, SGP1, FRA1, SYD1, and the newer BLR1. Region alignment reduces origin-fetch latency when the CDN edge has a cache miss. Enable the CDN toggle in the Spaces settings panel. DigitalOcean provisions a certificate automatically — no ACM request, no DNS validation step. The CDN endpoint is live within 60–90 seconds.
Add a CNAME record pointing your chosen subdomain (e.g., assets.yourdomain.com) to the CDN endpoint. In DigitalOcean's Spaces settings, add the custom domain. Certificate provisioning via Let's Encrypt happens automatically but can take up to 15 minutes the first time. One gotcha in 2026: if you use DigitalOcean's own DNS and App Platform for the apex domain, adding a Spaces CDN custom domain on a sibling subdomain works fine — but if you're using an external DNS provider, make sure you don't have a conflicting CAA record that blocks Let's Encrypt issuance.
This is where most setups break. Your App Platform app lives at app.yourdomain.com. Your Spaces CDN lives at assets.yourdomain.com. The browser treats these as different origins. Every fetch, every font load, every XHR to a presigned URL will fail without a correct CORS configuration on the Spaces bucket.
Set CORS rules on the bucket itself (via the API — the UI as of May 2026 still only supports basic wildcard configurations). The minimum viable CORS rule for most App Platform setups:
| Field | Value |
|---|---|
| AllowedOrigins | https://app.yourdomain.com (explicit, not wildcard) |
| AllowedMethods | GET, HEAD |
| AllowedHeaders | Content-Type, Range |
| MaxAgeSeconds | 86400 |
Critical detail: the Spaces CDN caches the CORS response headers along with the object. If you upload objects before setting CORS rules, the CDN may have already cached responses without Access-Control-Allow-Origin. You must purge the CDN cache after any CORS rule change. The 2026 Spaces API supports per-object purge via DELETE to the CDN endpoint with the X-CDN-Purge header, or full-bucket purge from the control panel. Per-object purge propagates in under 30 seconds; full purge can take up to 10 minutes.
Prior to January 2026, Spaces CDN applied a 24-hour default TTL to all objects regardless of origin headers. The new behavior respects your Cache-Control and Expires headers, falling back to a 1-hour TTL when neither is present. This is better for correctness but worse for hit ratios if you're lazy about headers.
Recommended approach: set Cache-Control: public, max-age=31536000, immutable on all content-hashed assets (JS bundles, CSS with hash filenames, processed images). For mutable paths like user avatars or config JSON, use Cache-Control: public, max-age=300, stale-while-revalidate=60. Your upload script or CI pipeline should stamp these headers at PUT time — Spaces does not support bucket-level default header policies.
When things go wrong — and in a two-origin architecture, they do — you need a fast diagnostic path. Here is the sequence we use:
Curl the object directly from the CDN endpoint with an Origin header matching your app. If the response lacks Access-Control-Allow-Origin, the CORS config is either missing or the CDN cached a pre-CORS response. Purge the specific object. Re-curl. If still missing, check that your CORS rule targets the correct bucket and that AllowedOrigins uses the scheme+host exactly (https, not http).
Confirm your build pipeline produces content-hashed filenames. If it does and stale content persists, the issue is likely an HTML file referencing old hashes — and that HTML is served by App Platform, not Spaces. Check App Platform's build cache settings. Force a clean build by toggling the "clear build cache" option in deployment settings.
Spaces CDN enforces the bucket's ACL. If you set objects to private and use presigned URLs, the CDN cannot cache them — presigned URLs bypass the CDN layer entirely. For CDN-served content, objects must be publicly readable. Mixed ACL states in a single bucket are the number-one cause of intermittent 403s.
If a CORS or cache change causes a production incident, the fastest rollback is to disable the CDN toggle on the bucket (reverts to origin-direct serving), fix the configuration, re-enable, and purge. The CDN disable/enable cycle takes about 90 seconds. During that window, clients hit the origin directly — latency increases, but availability holds.
Spaces CDN is a single-tier edge with no configurable cache rules, no edge compute, no request/response header manipulation, and no origin shield. For many workloads, that's fine. But you'll hit ceilings when you need: conditional redirects at the edge, A/B testing via edge logic, geographic access restrictions beyond IP-based rules, or sub-second purge propagation across all PoPs.
At that point, you keep Spaces as the origin and place an external CDN in front. The external CDN pulls from the Spaces origin URL (not the Spaces CDN URL — stacking two CDN layers creates cache-coherency nightmares). For organizations running significant transfer volume, cost becomes the deciding factor. BlazingCDN offers volume-based pricing starting at $4/TB ($0.004/GB) for up to 25 TB/month, scaling down to $2/TB at 2 PB+ — delivering stability and fault tolerance on par with Amazon CloudFront at a fraction of the cost. If your Spaces egress exceeds 5–10 TB/month consistently, the math tilts toward an external CDN in front of a Spaces origin, with the built-in Spaces CDN disabled.
| Monthly Transfer | Spaces CDN Cost (2026) | BlazingCDN Cost | Recommendation |
|---|---|---|---|
| 1 TB | $5 (included) | ~$4 | Stay with Spaces CDN — simplicity wins |
| 5 TB | $45 | ~$20 | External CDN starts to save money |
| 25 TB | $245 | $100 | External CDN — clear cost and feature advantage |
| 100 TB | $995 | $350 | External CDN — no question |
Spaces CDN cost calculated as: 1 TB included in the $5/month plan, $0.01/GB overage. BlazingCDN cost from published 2026 tier pricing.
Create a Spaces bucket in the same region as your App Platform app, enable the CDN toggle, and reference assets via the CDN endpoint URL in your frontend. App Platform serves your application; Spaces CDN serves your static assets. Configure CORS on the bucket to allow your App Platform origin.
Set a CORS rule on the bucket via the S3-compatible API with AllowedOrigins matching your App Platform domain exactly (including scheme). After setting or changing CORS rules, purge the CDN cache — the edge caches CORS headers alongside the response and will serve stale CORS results until purged.
Use the per-object purge via a DELETE request with the X-CDN-Purge header to the CDN endpoint, or trigger a full bucket cache purge from the control panel. Per-object purge completes in under 30 seconds; full purge takes up to 10 minutes as of May 2026.
Yes. CNAME your desired subdomain to the Spaces CDN endpoint, then add the custom domain in Spaces settings. DigitalOcean provisions a Let's Encrypt certificate automatically. Ensure no conflicting CAA DNS records exist that would block Let's Encrypt issuance.
When you need edge logic (redirects, A/B testing, header manipulation), sub-second global purge, or your monthly transfer consistently exceeds 5 TB. At that volume, an external CDN like BlazingCDN is both cheaper and more capable. Keep Spaces as the origin store; point the external CDN at the origin URL, not the Spaces CDN URL.
Pick one Spaces bucket that serves production assets. Curl three objects from the CDN endpoint with an Origin header set to your app's domain. Check every response for Access-Control-Allow-Origin, Cache-Control, and X-Cache (HIT vs MISS). If any of the three lack correct CORS headers or show shorter-than-expected TTLs, you've found work that will prevent an outage before it happens. Fix it, purge, verify. That's a 20-minute investment that pays off the next time you deploy on a Friday afternoon.
Learn
Best CDN for Video Streaming in 2026: Full Comparison with Real Performance Data If you are choosing the best CDN for ...
Learn
Video CDN Providers Compared: BlazingCDN vs Cloudflare vs Akamai for OTT If you are choosing a video CDN for an OTT ...
Learn
Video CDN Pricing Explained: How to Stop Overpaying for Streaming Bandwidth Video already accounts for 38% of total ...