Serving a video library from object storage and a CDN
Where to cache, what to sign and how to keep origin traffic predictable when a growing video catalogue is served from object storage.
A video library outgrows the application server long before it outgrows the business plan. The first thousand files sit happily on a mounted disk. At ten thousand, the disk is the deployment risk. At a hundred thousand, every scaling decision is really a storage decision.
The fix is not a bigger server. It is to stop treating video as application data at all: the catalogue lives in object storage, a CDN serves it, and the application only ever hands out URLs.
Object storage is the origin, not the delivery layer
Object storage is built for durability and parallel reads of whole objects. That is exactly what a video segment is. What it is not built for is absorbing the same read a hundred thousand times from a hundred thousand different places — that is what an edge cache is for.
So the shape is: bucket as origin, CDN in front, application out of the data path. The player fetches a manifest and segments from the CDN hostname. The CDN pulls from the bucket on a cache miss and holds the object for as long as the cache headers allow. On a warm library, origin traffic falls to a few per cent of delivered bytes.
Segment, then cache
Progressive download of a single large MP4 is the layout that makes caching useless: every viewer who seeks pulls a byte range the edge may not hold. Package to HLS or DASH instead. Segments of two to six seconds are individually cacheable, immutable, and small enough that a cold segment costs one short origin fetch rather than a gigabyte.
Two kinds of object then need two cache policies. Segments and renditions never change once written, so give them a long max-age and treat them as immutable. Manifests change when you add a rendition or a caption track, so keep their TTL short — thirty to sixty seconds is usually enough — or version the manifest path on publish and cache it as hard as the segments.
Never overwrite an object in place and expect the edge to notice. Write a new key. Cache invalidation across a global CDN is slower and less reliable than a new path, and a versioned key is auditable.
What to sign, and what not to
Public marketing trailers can be public objects. Anything gated needs a signed URL, and the mistake is signing the wrong thing for the wrong duration.
Sign the manifest request, keep the TTL short — ten to fifteen minutes is a good default — and let the player renew. A one-hour signature is a one-hour shareable link. A one-week signature is a leak. Where the CDN supports it, sign at the edge with a token that covers the whole path prefix, so a session gets one credential for the entire playback rather than a new signature per segment.
Keep the bucket itself private. The CDN should be the only reader, authenticated to the origin with its own scoped key. If the bucket is world-readable, the signature protects nothing — anyone who learns the origin hostname bypasses the edge entirely, and your delivery costs and access controls both stop meaning anything.
Keeping origin traffic predictable
The number to watch is not total bandwidth. It is the ratio of origin bytes to delivered bytes. Three failure modes push it the wrong way, and all three are avoidable.
The first is a long tail with no locality: a catalogue where every title gets a handful of views spread across regions means nothing stays warm at any edge. Accept it, and size for a lower hit rate rather than pretending the cache will save you.
The second is a launch. A new episode is a synchronised miss at every edge in the world. If the CDN supports origin shielding, turn it on — one designated cache absorbs the misses and the origin sees one fetch per segment instead of one per edge. Pre-warming the shield before an announced release does the same job.
The third is a misconfigured player asking for byte ranges the cache does not hold, or requesting a rendition ladder no one watches. Check what the player actually fetches before blaming the cache.
The operational parts nobody plans for
Lifecycle rules earn their place here. A media pipeline generates intermediate renditions, failed transcodes and stale thumbnails, and none of it should live forever. A rule that expires everything under a temporary prefix after thirty days keeps the bill flat without a cleanup script that someone has to remember.
Naming matters more than it looks. A prefix layout of title, then rendition, then segment lets you expire, migrate or audit a single title without touching the rest of the catalogue. A flat namespace of opaque UUIDs makes every future operation a full listing.
And keep the upload path separate from the delivery path. Ingest writes to one prefix with a private key, the transcoder writes finished renditions to another, and the CDN reads only the second. One-way flow means a bad upload cannot be served by accident.
The short version
Package to segments, cache the immutable parts hard and the manifests briefly, sign manifests with short TTLs and keep the bucket private to the CDN, watch the origin-to-delivered ratio rather than raw bandwidth, and let lifecycle rules clean up what the pipeline leaves behind. Done that way, a growing library is a storage line item, not an architecture project.
Antyxsoft object storage is built for read performance and works with any third-party CDN, with high durability and redundancy on every object — see how object storage works.
Antyxsoft Cloud
Written by the engineers who operate the Antyxsoft platform.