Storage & retention
Storage is one of the larger billing line items for live-streaming workloads, especially when you use the 24/7 DVR model. FrameWorks lets you keep the archive value without giving up cost control: live DVR can run continuously, completed assets can expire on a tenant default, and individual DVR / clip / VOD assets can be kept longer or shorter when they matter.
This page explains the underlying model so you can make informed retention decisions.
What gets stored, when
Section titled “What gets stored, when”| Asset type | Created when | Storage starts at |
|---|---|---|
| DVR | A record: true stream goes live (or startDVR) | First segment is written |
| Clip | createClip against a live stream or DVR recording | Asynchronous materialization |
| VOD asset | createVodUpload → completeVodUpload | Multipart upload completes |
DVR is the largest contributor for most accounts because a single 24/7 ingest can produce many hours of media per day.
Live DVR window vs retention
Section titled “Live DVR window vs retention”These are separate concepts and they’re often conflated:
- Live DVR window is how far back a live viewer can seek while the stream is still recording. It’s bounded by your tier and cluster so live HLS playlists stay small. This is not retention — the segments behind the window are still written to storage.
- Continuous archive is the full segment timeline of a stream session. It can be hours, days, or months long if the ingest stays live.
- Retention is how long a completed recording, clip, or VOD upload is kept. Retention is what controls long-term storage cost.
- Active DVR is not deleted by retention. Retention starts after the recording finalizes.
Per-class system defaults
Section titled “Per-class system defaults”Each asset class has its own default. VOD uploads are user-created library assets and default to keep forever. DVR recordings and clips default to 30 days because live recordings are typically ephemeral and clips are stream-derived.
| Asset class | System default |
|---|---|
| VOD upload | Keep forever |
| DVR | 30 days |
| Clip | 30 days |
Tier cap
Section titled “Tier cap”Every tier carries a single retention cap (bounds.maxRecordingRetentionDays on mediaRetentionPolicy). On paid tiers it is 0 — no cap. Free has a finite cap as an anti-abuse guardrail. The cap clamps everything below it (system default, tenant default, per-stream override, per-asset override), so a Free tenant who sets a per-asset override of 365 days lands at the Free cap instead.
Cascade
Section titled “Cascade”Effective retention for a new DVR, clip, or VOD asset is resolved in this order:
- Per-asset override (set via
updateMediaRetentionon a finalized asset) - Per-stream override (DVR / clip only — set via
setStreamRetentionOverrides) - Per-class tenant default (set via
setMediaRetentionPolicy) - Per-class system default (VOD: keep forever; DVR/clip: 30 days)
- Tier cap (clamps the result;
0= no cap on paid tiers)
The resolved value is snapshotted onto the artifact at creation / DVR start. Subsequent overrides update the artifact directly. Resetting a per-asset override re-anchors to the asset’s ended_at, so a 60-day-old clip reset to a 30-day default goes back to the same horizon it would have had under the cascade — not 30 days from today.
Tenant default policy
Section titled “Tenant default policy”Read the per-class defaults plus the values the cascade resolves to today and the tier cap:
query MediaRetentionPolicy { mediaRetentionPolicy { defaultVodRetentionDays # null = inherit system default defaultDvrRetentionDays defaultClipRetentionDays effectiveVodRetentionDays # what cascade resolves to today (0 = forever) effectiveDvrRetentionDays effectiveClipRetentionDays bounds { maxRecordingRetentionDays # 0 = no cap (paid baseline) } updatedBy updatedAt }}Set a tenant default for one asset class:
mutation SetMediaRetentionPolicy($input: SetMediaRetentionPolicyInput!) { setMediaRetentionPolicy(input: $input) { ... on MediaRetentionPolicy { effectiveVodRetentionDays effectiveDvrRetentionDays effectiveClipRetentionDays } ... on ValidationError { message field } }}Variables — “keep VOD forever, expire DVR after 90 days, expire clips after 14”:
{ "input": { "targetType": "VOD", "days": 0 } }{ "input": { "targetType": "DVR", "days": 90 } }{ "input": { "targetType": "CLIP", "days": 14 } }Clear a class default (fall back to system default):
{ "input": { "targetType": "DVR", "clear": true } }The webapp surfaces these on /account/storage under “Storage retention defaults”.
Per-stream override
Section titled “Per-stream override”DVR and clip retention can be overridden per stream. VOD uploads are not stream-bound and have no per-stream knob.
mutation SetStreamRetentionOverrides($input: SetStreamRetentionOverridesInput!) { setStreamRetentionOverrides(input: $input) { ... on StreamRetentionOverrides { streamId dvrRetentionDaysOverride clipRetentionDaysOverride } ... on ValidationError { message field } }}Each pair (value, clearXxxOverride) governs one column. To clear a previously-set override, pass clearDvrRetentionOverride: true (likewise for clip). Unset fields are left alone.
Per-asset override
Section titled “Per-asset override”Apply an override to a single finalized DVR, clip, or VOD asset. Override beats per-stream beats tenant default. Set targetType to DVR, CLIP, or VOD:
mutation UpdateRetention($input: UpdateMediaRetentionInput!) { updateMediaRetention(input: $input) { ... on EffectiveRetention { retentionDays retentionUntil source } ... on ValidationError { message field } ... on NotFoundError { message } }}Variables (DVR, 90 days): { "input": { "targetType": "DVR", "targetId": "<dvr id or hash>", "retentionDays": 90 } }
Variables (clip, keep forever): { "input": { "targetType": "CLIP", "targetId": "<clip id or hash>", "retentionDays": 0 } }
Variables (VOD, absolute): { "input": { "targetType": "VOD", "targetId": "<vod id or hash>", "retentionUntil": "2026-12-31T23:59:59Z" } }
Active recordings / in-flight uploads are rejected — overrides apply only to finalized assets. retentionDays: 0 is honored only on uncapped (paid) tiers; Free clamps it up to the cap.
Clear the override and recompute from the cascade:
mutation ResetRetention($input: ResetMediaRetentionOverrideInput!) { resetMediaRetentionOverride(input: $input) { ... on EffectiveRetention { retentionDays retentionUntil source } }}Effective retention on an asset
Section titled “Effective retention on an asset”DVRRequest.effectiveRetention, Clip.effectiveRetention, and VodAsset.effectiveRetention return the resolved horizon for a finalized asset (null while active for DVR):
query DVRRetention($id: ID!) { dvrRecordingsConnection(streamId: $id) { edges { node { dvrHash expiresAt effectiveRetention { retentionDays retentionUntil source } storageCost { perDay perMonth currency } } } }}storageCost is the marginal monthly amount the asset is adding to the tenant’s bill at the current tier. Null when pricing is unavailable (self-hosted or third-party-marketplace cluster — operator-absorbed).
Agent / MCP
Section titled “Agent / MCP”Agents manage retention via five MCP tools (cost-affecting; destructive-adjacent for update_asset_retention):
| Tool | Effect |
|---|---|
get_retention_policy | Reads tenant per-class defaults + tier cap + effective values. |
set_retention_policy | Writes a per-class tenant default (target_type, days, or clear). |
set_stream_retention_overrides | Writes per-stream DVR / clip overrides; clear_*_override flags reset a class to the tenant default. |
update_asset_retention | Per-asset override on a finalized DVR / clip / VOD (target_type + target_id; days=0 = keep forever). |
reset_asset_retention | Clears a per-asset override and re-anchors to the asset’s ended_at via the cascade. |
See agents/mcp for the full tool catalog.
Cost awareness
Section titled “Cost awareness”Retention is the main storage-cost control for always-on DVR, clips, and VOD. The storageCost field on each asset surfaces the marginal $/month it adds to the bill, so customers can decide whether to shorten retention or delete specific assets to recover cost. Shorter retention reduces stored bytes sooner; longer retention keeps more archive available. Use /account/storage to review current usage and adjust defaults before enabling long-running 24/7 DVR at scale.
Tenant policy changes emit media.retention_policy.changed. Per-asset changes emit media.retention.override_applied and media.retention.override_reset with the asset hash and new retention horizon.
Related
Section titled “Related”- Recordings, Clips & VOD — DVR / clip / VOD lifecycle
- Billing — tier pricing and storage line items
- Platform capabilities — where retention is exposed