Skip to content

Horizon Policy Syntax

ReferenceSQLStorage Policy
Opt-in Implemented · off by default — enable with enable_avmm = true · parsing and catalog persistence always work; the daemon only enforces (migrates tiers) when enable_avmm is set, which renders --enable-avmm

A horizon policy is a declarative rule set that decides which storage tier a table’s partitions live in — RAM, NVMe, or archive — based on their age, size, or row count. You declare it once with CREATE HORIZON POLICY; a background evaluator applies it on idle cycles, off the query path. This page is the precise grammar. For the concept and worked examples, see Horizon Materialization.

CREATE HORIZON POLICY <name> ON [TABLE] <table>
(WHEN <condition> THEN <action> [, WHEN <condition> THEN <action> ...])
  • The parentheses around the rule list are optional — a single bare WHEN … THEN … is accepted too.
  • Rules are separated by commas. At least one rule (or ALWAYS THEN …) is required.
  • Keywords are case-insensitive.
-- Parenthesized, multi-rule form
CREATE HORIZON POLICY log_retention ON events (
WHEN ts < NOW() - INTERVAL '30 DAYS' THEN SHADOW L3,
WHEN ts < NOW() - INTERVAL '365 DAYS' THEN ARCHIVE
);
-- Bare single-rule form
CREATE HORIZON POLICY hot_data ON events
WHEN older than 30 days THEN demote to warm;
-- Unconditional rule
CREATE HORIZON POLICY orders_pinned ON orders (ALWAYS THEN LUMINOUS);

Inspect what the evaluator is doing with:

SHOW HORIZON STATUS;

A condition is tested against each partition’s age, row count, and storage size.

ConditionFormMatches when
Age (older)OLDER THAN <n> <unit>partition age ≥ n units
Age (recent)WITHIN LAST <n> <unit>partition age ≤ n units
EpochEPOCH BEFORE <n>data written before epoch n
Row countROW COUNT EXCEEDS <n>partition has more than n rows
Storage sizeSTORAGE SIZE EXCEEDS <bytes>partition is larger than n bytes
UnconditionalALWAYSevery partition (use with THEN)

<unit> is DAYS, HOURS, or EPOCHS.

A SQL-expression time predicate of the form <column> < NOW() - INTERVAL 'N <unit>' is also accepted and translates to OLDER THAN; using > instead translates to WITHIN LAST.

ActionFormEffect
DemoteDEMOTE TO <tier>move to a colder tier
Demote (alias)SHADOW <tier>same as DEMOTE TO (e.g. SHADOW L3)
PromoteRESIDE IN <tier>move to a hotter tier
Pin to RAMLUMINOUSreside in the hottest tier
Promote (probe)PROMOTEreside in the hottest tier
ArchiveARCHIVE or ARCHIVE TO <target>move to external archive storage
DeleteDELETEdrop the partition
CompressCOMPRESS WITH <algo>zstd / lz4 / snappyparsed, not yet enforced (see below)
TierAliases accepted
Hot (RAM)hot, l1, luminous
Warm (mapped NVMe)warm, l2
Cold (NVMe)cold, l3, shadow
Archive (external)archive, l4
  • First match wins. For each partition the evaluator walks the rule list in order and applies the first rule whose condition matches; remaining rules are not considered.
  • No match → no move. A partition that matches no rule is left where it is.
  • Pinned partitions are never demoted, regardless of any rule.
  • If a policy has no explicit rules, the engine falls back to the legacy retention-window (age → demote) behavior.
  • Migrations run on the background tier-migration daemon, never on the query path — and only when enable_avmm is set.

CREATE HORIZON POLICY persists the rule set into the catalog and, when the daemon is enabled, immediately registers a translated copy with the in-memory tier-migration daemon (unit values are normalized to seconds and tier names to the engine’s tier enum). Because the daemon’s policy store is in-memory, it is re-hydrated from the catalog on startup — but only when enable_avmm is set. With the daemon disabled, policies are still parsed and stored; they just are not enforced until you enable it.