What is Just-in-Time Encoding?

Just-in-time encoding creates a requested media rendition on demand instead of precomputing every resolution, codec, or quality variant. The result may then be cached for later requests.

How Just-in-Time Encoding works

A just-in-time system puts the encoder behind the delivery URL. A request names a source and a recipe; a cache is checked for a stored result and the encode runs only on a miss, after which the output is returned and stored for later requests. That cache is a CDN in front of the encoder, a store the service manages itself, or both. An encoder with neither repeats the work on every request, and a stored result is reused only until it expires or is evicted. For images the unit of work is one URL. For video the practical unit is a segment of an adaptive stream rather than the whole file: an HLS player first requests playlists, which the service generates on the fly, and then requests short segments, each of which is encoded when it is first requested. Only the renditions and time ranges that are requested get encoded; players load segments ahead of the playback position, so that can include segments nobody ends up watching. Mux, which calls this just-in-time transcoding, describes streaming frames out of the transcoder before the rest of the file is complete.

Key facts

  1. Is just-in-time packaging the same thing? No. Just-in-time packaging rewraps renditions that already exist into the streaming format a player asks for. AWS Elemental MediaPackage describes it as creating a manifest in a format compatible with the requesting device; its source content comes from an upstream encoder for live video and, for video on demand, from HLS or MP4 files held in Amazon S3. The nginx-vod-module describes on-the-fly repackaging of MP4 files to DASH, HDS, HLS, and MSS. Neither describes encoding to a new resolution or bitrate, so the encoding ladder still has to be produced in advance. Just-in-time encoding defers that step too.
  2. What does the first request cost, and what if many arrive together? The first request for an output waits for the source to be fetched and for the encode; later requests are cache hits for as long as the result stays cached. imgproxy’s documentation notes that CDNs typically delete rarely accessed content, so a rarely requested output can be encoded more than once. Concurrent first requests for the same output can each start an encode unless the cache in front collapses them into one or the encoder shares the in-flight work itself, as the imagor image server does. Collapsing has conditions: Cloudflare collapses per data center, NGINX’s proxy_cache_lock is off by default, and on Fastly an uncacheable response makes queued requests go to the origin one after another.
  3. What happens to cached output when the encoding settings change? Nothing immediately, unless the change alters the cache key. A stored result is found by its key, typically the source, the processing options, and the output format, so a change to a server-side preset, quality default, or watermark that is not reflected in the request leaves old output in place until it expires or is invalidated. imgproxy documents a cachebuster URL option for exactly this case and notes that its internal cache has no manual invalidation, only expiration set on the storage behind it. Putting a version in the URL when a recipe changes gives the new output a new key straight away.
  4. What should happen when an encode fails? The error response needs its own cache policy. If it carries the lifetime of a successful result, a transient failure sticks: one imgproxy user reported a 504 response that was sent with a one-year Cache-Control header and stored by a downstream NGINX cache. If errors are never cached, every request for a broken source repeats the expensive failure. Without explicit caching headers, HTTP lets a cache store and reuse a 404, which is heuristically cacheable, but not a 500, 503, or 504. Cache-Control directives change that in either direction: max-age or public makes such an error storable, and no-store forbids storing any response.

When Just-in-Time Encoding matters

Just-in-time encoding pays off when you cannot predict which renditions, or which parts of a file, will be requested: large archives and user uploads where most material is rarely watched, or image sizes that depend on layouts you have not built yet. Encodes that nobody requests are never run. For rarely requested material, how long a result stays cached decides how often a repeat request pays for the encode again. Pre-encode instead when every output has to be ready before publication, when someone has to review it first, or when the first request has to be as fast as every later one. A fixed rendition ladder is not by itself a reason to pre-encode: a just-in-time encoder can serve predefined renditions and still skip the segments nobody requests.

How Transloadit helps with Just-in-Time Encoding

Transloadit offers just-in-time encoding through its Smart CDN. For video, the /video/ondemand Robot generates HLS playlists and segments on demand: a player requests the multivariant playlist from a tlcdn.com URL, each segment is encoded when it is first requested, and the Smart CDN caches playlists and segments for later viewers. For images and other files, a Smart CDN URL runs a Template on a cache miss and serves the cached result until it expires.

The /video/ondemand documentation describes HLS output. The /file/serve Robot sets how long results are cached: by default it tells CDNs to keep a result for 24 hours and browsers for 72 hours, and cache_duration changes both. When playlist URLs are signed with sign_urls_for, shorter expirations reduce cache reuse and can increase segment re-generation. The linked pages do not say what happens to results that are already cached when a Template is edited, or what a player receives when a segment encode fails, so test both before relying on them.

Explore Transloadit’s delivery capabilities

Sources

Turn media knowledge into a working pipeline

Connect uploads, processing, AI, storage, and delivery through one declarative API — with the encoding stack, scaling, and format churn handled for you.

Try Transloadit for free