Skip to Content
Manage & Flush

Manage & Flush

Managing a table attaches KoldStore policy and WAL mirror capture. Flushing moves eligible latest-state rows from the hot heap into Parquet and prunes them from PostgreSQL.

Enable management

Prefer named arguments. hot_row_limit is required in the manage_table call — pass NULL for hot-only tables that should not flush.

SQL
SELECT koldstore.manage_table(  table_name        => 'chat.messages',  storage           => 's3_archive',  hot_row_limit     => 10000,  min_flush_rows    => 1000,  max_rows_per_file => 1000,  auto_flush        => true,  migration_order_by => 'created_at');
ParameterDefaultMeaning
table_namerequiredTable to manage (regclass)
storagerequiredRegistered storage backend name
hot_row_limitrequired (NULL allowed)Max mirror rows to keep hot
min_flush_rows1000Minimum excess before a policy flush moves data
max_rows_per_file1000Max rows per Parquet segment (floor via koldstore.min_max_rows_per_file)
table_type'shared'shared or user (+ scope_column)
compressionNULLOptional Parquet codec (snappy, zstd, uncompressed)
target_file_size_mbNULLStored for future size-aware flush
auto_flushtrueLet the DB worker evaluate and run needed flushes

ALTER TABLE style

SQL
ALTER TABLE chat.messages SET (  koldstore_enabled = true,  koldstore_storage = 's3_archive',  koldstore_hot_row_limit = 10000,  koldstore_min_flush_rows = 1000,  koldstore_max_rows_per_file = 1000);

Age-based eviction (mutually exclusive with hot_row_limit):

SQL
ALTER TABLE chat.messages SET (  koldstore_enabled = true,  koldstore_storage = 's3_archive',  koldstore_move_after = '90 days',  koldstore_min_flush_rows = 1000,  koldstore_max_rows_per_file = 10000);

Age is measured from the latest captured mirror mutation encoded in seq.

Flush

Policy flush

SQL
SELECT koldstore.flush_table(table_name => 'chat.messages'::regclass);

Keeps the newest rows hot by mirror seq and flushes oldest eligible excess first, honoring hot_row_limit / min_flush_rows / max_rows_per_file.

Force flush

SQL
SELECT koldstore.flush_table(  table_name => 'chat.messages'::regclass,  force      => true);

Flushes all pending mirror rows. Use carefully on large tables.

Enqueue without running

SQL
SELECT koldstore.enqueue_flush_job(  table_name => 'chat.messages'::regclass,  force      => false);

Returns 1 if a job was inserted, 0 if an active flush job already exists. auto_flush does not gate manual flush / enqueue.

Inspect progress

SQL
SELECT jsonb_pretty(  koldstore.describe_table(table_name => 'chat.messages'::regclass)); SELECT koldstore.list_jobs(  statuses   => '["running","pending"]'::jsonb,  job_types  => '["flush"]'::jsonb,  table_name => 'chat.messages'::regclass);

Useful describe_table fields: hot_rows, mirror_rows, cold_row_count, cold_segment_count, heap/index sizes, manifest_state, pending_jobs, last_error.

Cancel

SQL
SELECT koldstore.cancel_job(job_id => '…'::uuid);SELECT koldstore.cancel_table_jobs(table_name => 'chat.messages'::regclass);

Pending jobs cancel immediately when unlocked. Running jobs stop cooperatively at the next wave boundary. If cancel lands after cold publish already committed, the job may finish completed with payload.cancel_requested_after_publish = true (data is not unpublished).

Auto-flush toggle

SQL
SELECT koldstore.set_table_auto_flush(  table_name => 'chat.messages'::regclass,  enabled    => false);

Manual flush_table still works. See Operations for the built-in worker tick and pg_cron fallback.

Unmanage

SQL
SELECT koldstore.unmanage_table(  table_name => 'chat.messages'::regclass,  rehydrate  => true,  drop_cold  => false);

Use this instead of koldstore_enabled = false. Optional rehydrate / drop_cold control whether cold rows return to the heap and whether cold objects are deleted.

Next

Last updated on