Skip to content

Storage & Tiered Storage

Meridian VMS uses a tiered storage system inspired by Milestone XProtect, where recordings flow through storage pools (hot, warm, cold) based on configurable policies. Each pool can use different media types, and recordings transition automatically between tiers as they age.

A storage pool is a named storage destination on a recording server. Each server can have multiple pools assigned to different physical media.

PoolMediaPurpose
HotNVMe / SSDActive recording target. Fastest I/O for concurrent writes from all cameras.
WarmHDD / RAIDMedium-term storage. Lower cost per TB for footage that is still accessed occasionally.
ColdNAS / network mount / cloudLong-term archive. Lowest cost for footage that is rarely accessed but must be retained.

Pools are configured per server from Settings > Servers > {server} > Storage Pools:

FieldDescription
NameDescriptive name (e.g., “SSD Primary”, “HDD Archive”, “NAS Cold”)
PathFilesystem path on the recording server (e.g., /recordings/hot, /mnt/nas/archive)
TypeHot, Warm, or Cold
Max Usage %Stop writing to this pool when disk usage exceeds this threshold (default: 90%)

Each recording server must have at least one Hot pool configured. Warm and Cold pools are optional.

A storage policy defines the lifecycle of recordings — how long they stay in each pool tier before transitioning or being deleted.

Each policy specifies retention per tier:

TierRetentionDescription
Hot3 daysRecordings stay on fast SSD for 3 days
Warm30 daysAfter 3 days, move to HDD for up to 30 days
Cold365 daysAfter 30 days, move to NAS/cloud for up to 365 days

After the final tier’s retention expires, recordings are permanently deleted.

Create policies from Settings > Storage > Policies:

Policy: "Standard Retention"
Hot: 3 days --> pool: SSD Primary
Warm: 30 days --> pool: HDD Archive
Cold: 365 days --> pool: NAS Cold
Policy: "High Security"
Hot: 7 days --> pool: SSD Primary
Warm: 90 days --> pool: HDD Archive
Cold: 730 days --> pool: NAS Cold
Policy: "Short Term"
Hot: 14 days --> pool: SSD Primary
(no warm or cold -- delete after 14 days)

Policies are assigned at two levels:

LevelDescription
SiteAll cameras at a location (site) use this policy by default
CameraOverride the site policy for a specific camera

Camera-level assignment takes precedence over site-level. If neither is set, the system-wide default policy applies.

Configure assignments from Settings > Locations > {site} > Storage Policy or Settings > Cameras > {camera} > Storage Policy.

Recordings move between pools in automated batch operations:

  1. A background scheduler runs every 15 minutes on each recording server.
  2. For each camera, it evaluates the assigned storage policy.
  3. Segments in the Hot pool older than the hot retention period are queued for transition to Warm.
  4. Segments in the Warm pool older than the warm retention period are queued for transition to Cold.
  5. Segments in the Cold pool older than the cold retention period are queued for deletion.
  6. The batch mover copies segment files to the destination pool, verifies integrity (checksum), and updates the segment index in the management database.
  7. After successful copy and index update, the source file is deleted.
FactorImpact
File sizeLarger segments (longer duration) move faster per unit of footage
I/O bandwidthSSD to HDD transitions are limited by HDD write speed
Network speedTransitions to NAS/cloud pools are limited by network throughput
Concurrent movesConfigurable concurrency limit prevents saturating I/O (default: 4 concurrent file moves)

In multi-server deployments, each recording server manages its own pools independently. The management server maintains a unified segment index that tracks which server and pool holds each segment.

The management server proxies storage queries across all recording servers:

MethodEndpointDescription
GET/api/servers/{id}/poolsList pools on a recording server
GET/api/servers/{id}/pools/{pool}/usageDisk usage for a specific pool
GET/api/servers/{id}/pools/{pool}/segmentsBrowse segments in a pool

When playing back footage, the management server automatically routes segment requests to whichever server and pool currently holds the data. Operators do not need to know which tier or server stores a specific segment.

Each tier in a storage policy has its own retention period. The retention daemon on each recording server evaluates all tiers:

  1. Hot tier cleanup — Moves aged segments to Warm (or deletes if no Warm tier).
  2. Warm tier cleanup — Moves aged segments to Cold (or deletes if no Cold tier).
  3. Cold tier cleanup — Deletes segments past the cold retention period.

When a pool exceeds its configured maximum usage percentage:

StrategyBehavior
Stop RecordingPause recording on cameras assigned to the full pool (default)
Overwrite OldestDelete the oldest segments in the pool to free space
Overflow to Next TierMove segments to the next tier early, bypassing normal retention

Recordings are stored as fMP4 (fragmented MP4) segments:

/recordings/{pool_path}/{camera_id}/YYYY/MM/DD/HHMM.mp4
ComponentDescription
{pool_path}The pool’s filesystem path
{camera_id}UUID of the camera
YYYY/MM/DD/Date-based directory structure
HHMM.mp4Segment file named by start time

Segments preserve the original camera stream with no re-encoding. The original camera codec (H.264 or H.265) is preserved byte-for-byte.

DurationDefaultRange
Segment time120 seconds60s to 3600s

Configure from Settings > Storage > Segment Duration. Changing the segment duration restarts the recording processes on all servers.

Every segment is indexed in the management database with its camera, server, pool, file path, start and end timestamps, file size, and current storage tier. The index is optimised for fast timeline queries and playback lookups.

Settings > Storage > Danger Zone includes:

  • Delete All Recordings — Permanently deletes all segments from all servers and pools. Requires double confirmation.
  • Reset Pool Configuration — Removes all pools and reverts to single-path storage. Existing segments remain on disk but must be re-indexed.
MethodEndpointDescription
GET/api/settings/storageGet storage configuration
PATCH/api/settings/storageUpdate storage settings
GET/api/storage/poolsList all pools across all servers
POST/api/storage/poolsCreate a storage pool
PATCH/api/storage/pools/{id}Update a pool
DELETE/api/storage/pools/{id}Delete a pool
GET/api/storage/policiesList storage policies
POST/api/storage/policiesCreate a storage policy
PATCH/api/storage/policies/{id}Update a policy
DELETE/api/storage/policies/{id}Delete a policy
DELETE/api/settings/recordingsDelete all recordings