Rule examples: HLS
HLS (HTTP Live Streaming) splits a stream into a text manifest (.m3u8) that lists short media segments (.ts or .m4s). The CDN has to cache these two file types very differently: the manifest changes every few seconds as the live edge advances, while each segment is immutable once published. This page gives you a ready-to-use template of cache rules and a CORS header rule for serving HLS from your own packaged streams.
Why manifests and segments need different TTLs
A live HLS manifest is rewritten on every segment boundary — it always points at the newest few segments. If the CDN over-caches the manifest, players keep replaying a stale window and playback stalls. Segments, by contrast, never change once written: a given segment_042.ts is the same bytes forever (within the rolling DVR window), so a slightly longer TTL is safe and reduces origin load.
| File type | Pattern (case-insensitive regex) | TTL | Why |
|---|---|---|---|
| Manifest / playlist | ~* \.(m3u8)$ | 2 seconds | Must stay fresh; the live edge advances every segment. |
| Media segment | ~* \.(ts|m4s)$ | 10 seconds | Immutable within the rolling window; caching longer adds no benefit. |
Keep the manifest TTL low (1–2 seconds) and the segment TTL modest (5–10 seconds). Caching manifests too long is the single most common cause of stalled or "stuck" live playback.
Manifest cache rule
Create a cache rule that matches .m3u8 playlists with a 2-second TTL. The pattern uses the case-insensitive regex operator, so use the Regex match type (matchType: 4).
{
"name": "HLS manifest",
"pattern": "\\.(m3u8)$",
"matchType": 4,
"ttlSeconds": 2,
"description": "Keep HLS playlists fresh — live edge follows the manifest",
"order": 1,
"isEnabled": true
}
Post it to your property:
curl -X POST 'https://api.paradarum.com/api/Property/42/rules/cache' \
-H 'X-Api-Key: pdm_YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "HLS manifest",
"pattern": "\\.(m3u8)$",
"matchType": 4,
"ttlSeconds": 2,
"description": "Keep HLS playlists fresh",
"order": 1,
"isEnabled": true
}'
Segment cache rule
Match the media segments (.ts for MPEG-TS, .m4s for fragmented MP4) with a 10-second TTL. Give it a higher order so the manifest rule is evaluated first.
{
"name": "HLS segment",
"pattern": "\\.(ts|m4s)$",
"matchType": 4,
"ttlSeconds": 10,
"description": "Immutable segments within the rolling window",
"order": 2,
"isEnabled": true
}
curl -X POST 'https://api.paradarum.com/api/Property/42/rules/cache' \
-H 'X-Api-Key: pdm_YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "HLS segment",
"pattern": "\\.(ts|m4s)$",
"matchType": 4,
"ttlSeconds": 10,
"description": "Immutable segments within the rolling window",
"order": 2,
"isEnabled": true
}'
The pattern is a PCRE regular expression matched against the request URL. In JSON you must escape the backslash, so \.(ts|m4s)$ becomes "\\.(ts|m4s)$". The leading ~* you may see in nginx-style configs corresponds to the case-insensitive Regex match type and is not part of the pattern value you send.
CORS header rule for browser players
Browser-based players such as hls.js fetch the manifest and segments with XHR/fetch, so the responses need an Access-Control-Allow-Origin header or the browser blocks them. Add a response header rule with the Set action (action: 1), an empty pattern (so it applies to every request), and applyToRequest: false so it lands on the response.
{
"name": "HLS CORS",
"pattern": "",
"matchType": 1,
"action": 1,
"headerName": "Access-Control-Allow-Origin",
"headerValue": "*",
"applyToRequest": false,
"order": 3,
"isEnabled": true
}
curl -X POST 'https://api.paradarum.com/api/Property/42/rules/header' \
-H 'X-Api-Key: pdm_YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "HLS CORS",
"pattern": "",
"matchType": 1,
"action": 1,
"headerName": "Access-Control-Allow-Origin",
"headerValue": "*",
"applyToRequest": false,
"order": 3,
"isEnabled": true
}'
action: 1 is Set/Replace in the header rule actions. An empty pattern makes the rule global, regardless of the match type. Set the value to a specific origin instead of * if you want to restrict which sites may embed your player.
Request flow
A note on Paradarum Live properties
If you publish through Paradarum Live, you do not create these rules yourself. When a live stream is provisioned, the backing CDN property is created with equivalent system rules already in place — a manifest rule, a segment rule, and a CORS rule — and they are read-only on that managed property. The system manifest rule actually combines HLS and DASH with the pattern ~* \.(m3u8|mpd)$, and the segment rule covers ~* \.(ts|m4s)$. See live playback and caching for details.
On a managed live property the HLS/DASH/CORS rules are flagged as system rules and shown read-only — do not try to hand-edit them. Use the template on this page only for custom HLS delivery on a standard property where you package the stream yourself.
See also
- Rule examples: DASH — the equivalent rules for MPEG-DASH (
.mpd/.m4s). - Live playback and caching — the system rules on managed live properties.
- Header rules — full reference for the CORS action used above.
- Cache rules and match operators — TTLs and the Regex match type.