Skip to Content
Getting Started

Getting Started

This walkthrough creates a managed table on local filesystem storage, flushes excess rows to Parquet, and shows both merge-scan reads and the change feed.

Prerequisites: Installation completed — shared_preload_libraries includes koldstore, wal_level=logical, and CREATE EXTENSION koldstore succeeded.

1. Register storage

SQL
SELECT koldstore.register_storage(  name         => 'local-dev',  storage_type => 'filesystem',  base_path    => '/tmp/koldstore-demo',  credentials  => '{}'::jsonb,  config       => '{}'::jsonb);

storage_type may also be s3, gcs, or azure. For MinIO-style S3:

SQL
SELECT koldstore.register_storage(  name         => 'minio',  storage_type => 's3',  base_path    => 'koldstore-bucket',  credentials  => '{"access_key_id":"minioadmin","secret_access_key":"minioadmin"}'::jsonb,  config       => '{"endpoint":"http://127.0.0.1:9000","region":"us-east-1","path_style":true}'::jsonb);

2. Create a normal heap table

Managed tables need a primary key. Supported types today include boolean, integers, real, double precision, text, varchar, uuid, jsonb, and timestamptz.

SQL
CREATE SCHEMA IF NOT EXISTS app; CREATE TABLE app.messages (  id bigint PRIMARY KEY,  body text NOT NULL,  created_at timestamptz NOT NULL DEFAULT now()); INSERT INTO app.messages (id, body)SELECT gs, 'row ' || gsFROM generate_series(1, 1012) AS gs;

3. Manage the table

Two equivalent styles:

A. manage_table (structured options)

SQL
SELECT koldstore.manage_table(  table_name         => 'app.messages',  storage            => 'local-dev',  hot_row_limit      => 1000,  min_flush_rows     => 1,  max_rows_per_file  => 500,  migration_order_by => 'id');

B. ALTER TABLE options

SQL
ALTER TABLE app.messages SET (  koldstore_enabled = true,  koldstore_storage = 'local-dev',  koldstore_hot_row_limit = 1000,  koldstore_min_flush_rows = 1,  koldstore_max_rows_per_file = 500);

Do not turn management off with koldstore_enabled = false — use koldstore.unmanage_table(...) instead. Storage cannot be changed after manage.

With hot_row_limit set, manage_table rejects non-PK UNIQUE constraints and foreign keys (those stay hot-only after flush). See Status & Limits.

4. Fence the async mirror

Foreground DML writes the heap only. A database worker applies committed WAL into the latest-state mirror (koldstore.messages__cl) with short lag. Before work that must observe every commit visible at the start of the call:

SQL
SELECT koldstore.wait_for_async_mirror();

flush_table runs this fence automatically.

5. Page the change feed

SQL
SELECT seq, op, pk, deleted, sourceFROM koldstore.changes_since(  table_name => 'app.messages'::regclass,  since_seq  => 0,  limit_rows => 100);

Resume with an exclusive cursor (seq > since_seq). Or rewind to the newest N rows (delivered oldest → newest) when since_seq = 0:

SQL
SELECT seq, op, pk, deleted, sourceFROM koldstore.changes_since(  table_name => 'app.messages'::regclass,  since_seq  => 0,  limit_rows => 1000,  last_rows  => 50);

Full semantics: Change Feed.

6. Flush excess rows to cold storage

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

With hot_row_limit = 1000 and more than 1000 mirror keys, the oldest excess rows (by mirror seq) move to Parquet and leave the hot heap. Inspect status:

SQL
SELECT jsonb_pretty(  koldstore.describe_table(table_name => 'app.messages'::regclass));

7. Query one table

SQL
SELECT count(*) FROM app.messages;  -- hot + cold via KoldMergeScanSELECT * FROM app.messages WHERE id = 1;

After flush, cold-capable plans show KoldMergeScan. Hot-only PK lookups that cannot hit cold may keep a native Index/Seq/Bitmap Scan with no wrapper — that path is intentional and performance-critical.

What just happened

  1. PostgreSQL still owns transactions, MVCC, permissions, and the hot heap
  2. WAL capture wrote latest-state rows into koldstore.messages__cl
  3. Flush published Parquet segments and pruned flushed hot/mirror rows
  4. SELECT merges hot + cold; changes_since pages the same latest-state stream

Next: Under the Hood for the architecture, or Manage & Flush for policy details.

Last updated on