KDB knowledge

Versions and upgrades

A new KDB opens the data of an older KDB. An older KDB refuses the data of a newer KDB with "needs a newer KDB" and changes nothing.

The rule:

How it works: every database keeps a feature list in its manifest. A feature is one change to what KDB writes on disk, for example json (a JSON column) or sequences (CREATE SEQUENCE). KDB adds a feature to the list before it writes the first data that needs it. When a database opens, KDB reads the list first. A name it does not know means: a newer KDB wrote this. Only schema statements (CREATE, ALTER, ...), first uses and checkpoints look at the list, so rows cost nothing extra.

A database made by a KDB before feature lists (before 2026-09-12) has no list. It opens as always. KDB works out its list from the tables, files and log, and saves it at the next checkpoint (or now, with kdb upgrade).

kdb version <db>

Syntax:

kdb version
kdb version <db> [--data-dir <folder>]

Without <db>: this KDB and every feature it can read. With <db>: the feature list of that database (read from its manifest, so it also works while a server has the database open).

Command line: This KDB and the features it reads

kdb version

Output:

kdb 0.2.0-dev (crc32c hardware: yes)
tls: OpenSSL 3.6.3 9 Jun 2026

Stored-format features this build reads (51):
  views                0.2.0-dev (2026-09-10)   CREATE VIEW: the "views" file
  partition_format_2   0.2.0-dev (2026-09-11)   table partition files in format 2 (one raw block per column)
  block_stats          0.2.0-dev (2026-09-11)   column stats section in partition files (count, min, max, sum per column)
  runs                 0.2.0-dev (2026-09-11)   log record 'C': rows of a bulk upsert kept as columns
  auto_meta            0.2.0-dev (2026-09-11)   AUTO id counters in the manifest (auto.<table id>)
  json                 0.2.0-dev (2026-09-11)   JSON columns (type code 12)
  bytes                0.2.0-dev (2026-09-11)   BYTES columns (type code 13)
  check                0.2.0-dev (2026-09-11)   CHECK constraints (catalog format 2, part 'C')
  indexes              0.2.0-dev (2026-09-11)   CREATE INDEX, UNIQUE and FULLTEXT indexes (catalog part 'I')
  routines             0.2.0-dev (2026-09-11)   functions, procedures and triggers: the "routines" file
  users                0.2.0-dev (2026-09-11)   server users and roles (_system.users)
  audit                0.2.0-dev (2026-09-12)   SET AUDIT ON: catalog part 'A', log record 'P', the _audit_log table
  table_grants         0.2.0-dev (2026-09-12)   GRANT ... ON TABLE (_system.users.table_grants)
  totp                 0.2.0-dev (2026-09-12)   two-factor logins (_system.users.totp)
  trash                0.2.0-dev (2026-09-12)   dropped tables kept as _dropped_<ms>_<name> for UNDROP TABLE
  database_settings    0.2.0-dev (2026-09-12)   ALTER DATABASE ... SET READ ONLY (_system.database_settings)
  dialects             0.2.0-dev (2026-09-12)   ALTER DATABASE ... SET dialect (_system.database_dialects)
  pg_catalog_parts     0.2.0-dev (2026-09-12)   PostgreSQL column types, multi-column keys, foreign keys, expression and partial indexes (catalog parts 'T', 'K', 'F', 'X')
  sequences            0.2.0-dev (2026-09-12)   CREATE SEQUENCE: the "sequences" file and its log records
  batched_log_sync     0.2.0-dev (2026-09-11)   log segments in the batched format (header flag 1, 16-byte commit records): group commit and --sync-commits batch
  dedup_change         0.2.0-dev (2026-09-12)   ALTER TABLE ... DEDUP ENABLE / DISABLE: the DEDUP KEY of a table that already holds rows
  plpgsql_triggers     0.2.0-dev (2026-09-12)   PostgreSQL plpgsql trigger functions and FOR EACH ROW triggers in the "routines" file
  cached_views         0.2.0-dev (2026-09-13)   CREATE CACHED VIEW: which views are cached, and REFRESH ON COMMIT, in the "views" file
  deferred_triggers    0.2.0-dev (2026-09-13)   CREATE TRIGGER ... DEFERRED: job records in the log, and the "trigger_queue" and "q/<job>" files of queued jobs
  materialized_views   0.2.0-dev (2026-09-13)   CREATE MATERIALIZED VIEW: catalog part 'M', REFRESH MATERIALIZED VIEW log records, mv_dirty.<id> in the manifest
  table_ttl            0.2.0-dev (2026-09-13)   TTL n DAYS on a table: catalog part 'L'
  read_only_procedures 0.2.0-dev (2026-09-24)   CREATE PROCEDURE ... READ ONLY in the "routines" file
  dedup_insert         0.2.0-dev (2026-09-24)   WITH (dedup_insert = 'upsert') on a table: catalog part 'U'
  decimal128           0.2.0-dev (2026-09-25)   NUMERIC(p, s) columns with more than 18 digits: 128-bit DECIMAL (type code 14) in the catalog, partition files and log
  dedup_generated_key  0.2.0-dev (2026-09-25)   a stored generated column in a DEDUP KEY, like the minute of the time (an older build refuses such a catalog)
  symbol_partitions    0.2.0-dev (2026-09-25)   PARTITION BY <time>, SYMBOL(col): catalog part 'P' (one partition file per time bucket and symbol, t/<id>/<time>/s-...)
  round_time_zone      0.2.0-dev (2026-09-25)   TIMESTAMP ROUND ... TIME ZONE 'zone' columns: catalog part 'R'
  enum_types           0.2.0-dev (2026-09-25)   CREATE TYPE ... AS ENUM: the ENUM types after the tables of the catalog (catalog format 3)
  row_ttl              0.2.0-dev (2026-09-25)   CREATE TABLE ... WITH (ttl_column = c): rows expire one by one, catalog part 'E'
  column_compression   0.2.0-dev (2026-09-25)   ALTER TABLE ... SET (compression = on): catalog part 'Z' and packed partition files (header flag 2)
  calendars            0.2.0-dev (2026-09-25)   CREATE CALENDAR: trading calendars (eras, holidays, extra trading days) after the ENUM types of the catalog (catalog format 4)
  materialized_view_sample_by 0.2.0-dev (2026-09-26)   CREATE MATERIALIZED VIEW ... AS (SELECT ... SAMPLE BY ...): a SAMPLE BY query in catalog part 'M', refreshed bucket by bucket
  comments             0.2.0-dev (2026-09-26)   COMMENT ON TABLE / COLUMN: the comments of a table and its columns, catalog part 'N'
  cache_tables         0.2.0-dev (2026-10-02)   WITH (max_bytes, evict, durability): cache tables with a memory cap and eviction, catalog part 'Y'
  resident_tables      0.2.0-dev (2026-10-02)   WITH / SET (resident = on): a table never unloaded to make room, catalog part 'H'
  partition_tails      0.2.0-dev (2026-10-02)   tail files: rows appended to a partition saved in extra files t/<id>/<partition>.tail<k>.b<version> (tail_files)
  uuid                 0.2.0-dev (2026-10-02)   UUID columns: 16 bytes per value (type code 15) in the catalog, partition files and log
  search_analyzer      0.2.0-dev (2026-10-02)   CREATE FULLTEXT INDEX ... WITH (language = 'english'): the word analyzer of a full-text index, catalog part 'S'
  column_grants        0.2.0-dev (2026-10-02)   GRANT / REVOKE on single columns (_system.users.column_grants)
  row_policies         0.2.0-dev (2026-10-02)   row-level security: CREATE POLICY and ALTER TABLE ... ENABLE ROW LEVEL SECURITY (_system.row_policies)
  partition_deltas     0.2.0-dev (2026-10-02)   delta files: a few rows of a partition replaced or deleted, saved in t/<id>/<partition>.delta.b<version>
  fulltext_segments    0.2.0-dev (2026-10-02)   full-text and JSON index segments in fts/*.kfs (the words of each partition's rows; never recorded: an older build ignores them)
  compressed_log       0.2.0-dev (2026-10-02)   packed log records (type 3): the data records of a big commit written compressed (KDB_WAL_COMPRESS)
  endpoints            0.2.0-dev (2026-10-03)   CREATE ENDPOINT: saved queries served at GET /v/<name>, kind 'E' in the routines file
  rules                0.2.0-dev (2026-10-03)   CREATE RULE: named checks, session hours and settings of a table (catalog part 'Q')
  sync_commit_tables   0.2.0-dev (2026-10-03)   WITH (synchronous_commit = on | off) of a table: catalog part 'G'

A database that uses a feature not in this list needs a newer KDB (kdb check exits with 3).

Command line: The features of one database (sample data: sample)

kdb version market

Output:

kdb 0.2.0-dev (crc32c hardware: yes)
database market
feature list (4):
  batched_log_sync     log segments in the batched format (header flag 1, 16-byte commit records): group commit and --sync-commits batch
  block_stats          column stats section in partition files (count, min, max, sum per column)
  compressed_log       packed log records (type 3): the data records of a big commit written compressed (KDB_WAL_COMPRESS)
  partition_format_2   table partition files in format 2 (one raw block per column)

SHOW VERSION

Syntax:

SHOW VERSION

This KDB's version, and for the current database: the features it uses now and the list saved in its manifest. Every user may run it (it shows no data).

itemvalue
kdb versionthe version of this KDB
databasethe current database
features usedwhat the database uses now
feature listsaved: ..., or not saved yet (written by an older KDB)
features this KDB readshow many, and their names

Example: SHOW VERSION (sample data: sample)

SHOW VERSION;

Result:

item (STRING)value (STRING)
kdb version0.2.0-dev
databasedemo
features usedbatched_log_sync, block_stats, compressed_log, partition_format_2
feature listsaved: batched_log_sync, block_stats, compressed_log, partition_format_2
features this KDB reads51: views, partition_format_2, block_stats, runs, auto_meta, json, bytes, check, indexes, routines, users, audit, table_grants, totp, trash, database_settings, dialects, pg_catalog_parts, sequences...

(5 rows)

kdb upgrade

Syntax:

kdb upgrade <db> [--backups <dir>] [--data-dir <folder>]

Makes a database ready for this KDB, in three steps:

  1. A verified backup into --backups <dir> (default: a folder <db folder>-backups next to the database; for a name in the data folder <data folder>-backups/<name>). Older backups there are kept.
  2. Saves the database's feature list (and writes anything a newer format needs; this version needs nothing more).
  3. Runs kdb check.

Command line: Upgrade a database (sample data: sample)

kdb upgrade market --backups backups

Output:

KDB 0.2.0-dev, database market
saved feature list: batched_log_sync, block_stats, compressed_log, partition_format_2
1/3 verified backup into backups ...
    backups/20261022-054442-544 (9 files, 190.0 KB)
2/3 saving the feature list ...
    features used: batched_log_sync, block_stats, compressed_log, partition_format_2
    (no files need to be written again for this KDB version)
3/3 check ...
checked 14 files (76.1 KB) and 1 log segments
OK: no damage found

Upgrade done. An older KDB build that does not know one of these features now refuses this database with "needs a newer KDB".

Going back to an older version

Syntax:

kdb features <db> | --data-dir <folder>
kdb downgrade <db> | --data-dir <folder> --to <version> [--backups <dir>] [--no-backup]
kdb downgrade <db> | --data-dir <folder> --known <feature,feature,...>

An older KDB opens a database again when the data uses nothing newer than that KDB reads. The feature list only grows, so it may still name a feature you stopped using: a dropped column, a dropped procedure. kdb downgrade takes those names off.

kdb features shows what each database uses now, and what uses it. It changes nothing.

kdb downgrade works in three steps:

  1. A verified backup (as kdb upgrade makes it). --no-backup skips it.
  2. A checkpoint, so nothing waits in the log. Then the feature list becomes exactly what the data uses.
  3. kdb check.
OptionWhat it means
--to 2026-09-24a KDB built on that day: it reads every feature written since that day or before
--to 0.2.0-devthe last KDB of that version
--known views,indexes,...exactly these features: the names kdb version of the older KDB prints
--data-dir <folder> without <db>every database of the data folder, _system too. All are checked before any is changed.

Command line: What a database uses now (sample data: sample)

kdb features market

Output:

database market
in use now (4):
  partition_format_2     0.2.0-dev (2026-09-11)
      used by: the table files
  block_stats            0.2.0-dev (2026-09-11)
      used by: the table files
  batched_log_sync       0.2.0-dev (2026-09-11)
      used by: the log (group commit writes every log segment this way)
  compressed_log         0.2.0-dev (2026-10-02)
      used by: the log (big commits are written as packed records)

Command line: Let a KDB of 24 Sep 2026 open the data (sample data: sample)

kdb downgrade market --to 2026-09-24 --backups backups

Output:

KDB 0.2.0-dev: downgrade to 2026-09-24

database market
1/3 verified backup into backups ...
    backups/20261022-054442-754 (9 files, 190.0 KB)
2/3 checkpoint, then the feature list ...
    list before: batched_log_sync, block_stats, compressed_log, partition_format_2
    list now:    batched_log_sync, block_stats, partition_format_2
    taken off (no longer used): compressed_log
3/3 check ...
checked 14 files (76.1 KB) and 1 log segments
OK: no damage found

Downgrade done. Stop this KDB and start the older one on the data. Opening the data with this KDB again is fine: it adds features to the list as they are used.

Command line: Refused: a 128-bit NUMERIC column is in use

Setup:

CREATE TABLE prices (id LONG, amount NUMERIC(30, 4));
kdb downgrade market --to 2026-09-24 --no-backup

Output:

KDB 0.2.0-dev: downgrade to 2026-09-24

database market uses features the older KDB does not read:
  decimal128             0.2.0-dev (2026-09-25)
      used by: column 'amount' of table 'prices' (NUMERIC with more than 18 digits)
      to remove: ALTER TABLE prices DROP COLUMN amount

Nothing was changed. Remove what is listed (a dropped table stays in the trash until DROP TABLE _dropped_<time>_<name>), or keep this KDB. The command only goes back when the data uses nothing newer.

exit code 1

"needs a newer KDB"

Syntax:

error: this database needs a newer KDB: it uses <feature> (a stored-format feature this KDB build does not know). Nothing was changed

The database was written by a newer KDB. It is not damaged.

The features

FeatureWhat a database with it hasWritten since
viewsCREATE VIEW (the "views" file)0.2.0-dev (2026-09-10)
partition_format_2table partition files in format 22026-09-11
block_statscount, min, max and sum per column in partition files2026-09-11
runslog records of bulk upserts kept as columns (line protocol)2026-09-11
auto_metaAUTO id counters in the manifest2026-09-11
json, bytesJSON and BYTES columns2026-09-11
checkCHECK constraints2026-09-11
indexesCREATE INDEX, UNIQUE, FULLTEXT2026-09-11
routinessaved functions, procedures, triggers2026-09-11
usersserver users (in _system)2026-09-11
batched_log_synclog files in the batched form: group commit (the default) and --sync-commits batch write them, so every database has it2026-09-11
auditALTER TABLE ... SET AUDIT ON, _audit_log2026-09-12
table_grants, totpGRANT ... ON TABLE, two-factor logins (in _system)2026-09-12
trashdropped tables kept for UNDROP TABLE2026-09-12
database_settings, dialectsALTER DATABASE ... SET READ ONLY / SET dialect (in _system)2026-09-12
pg_catalog_partsPostgreSQL types, multi-column keys, foreign keys, expression and partial indexes2026-09-12
sequencesCREATE SEQUENCE2026-09-12
dedup_changeALTER TABLE ... DEDUP ENABLE / DISABLE on a table that already holds rows2026-09-12
plpgsql_triggersPostgreSQL plpgsql trigger functions and FOR EACH ROW triggers2026-09-12
cached_viewsCREATE CACHED VIEW: which views are cached and REFRESH ON COMMIT, kept in the "views" file2026-09-13
deferred_triggersCREATE TRIGGER ... DEFERRED: job records in the log, and the "trigger_queue" and "q/..." files of waiting jobs2026-09-13
materialized_viewsCREATE MATERIALIZED VIEW: the view's query in the catalog, refresh records in the log, waiting partitions in the manifest2026-09-13
table_ttlTTL n DAYS on a table, kept in the catalog2026-09-13
read_only_proceduresCREATE PROCEDURE ... READ ONLY, kept with the procedure2026-09-24
dedup_insertWITH (dedup_insert = 'upsert') on a table, kept in the catalog2026-09-24
decimal128NUMERIC(p, s) columns with more than 18 digits (128 bits each)2026-09-25
uuidUUID columns, 16 bytes per value (UUID)2026-10-02
column_grantsGRANT SELECT (a, b) ON TABLE t (column rights; in _system, only once one is granted)2026-10-02
row_policiesCREATE POLICY, ALTER TABLE t ENABLE ROW LEVEL SECURITY (row rights; in _system, only once one is made)2026-10-02
dedup_generated_keya stored generated column in a DEDUP KEY, like the minute of the time2026-09-25
symbol_partitionsPARTITION BY ..., SYMBOL(col) (split by symbol)2026-09-25
round_time_zonea column TIMESTAMP ROUND 1d TIME ZONE 'Asia/Kathmandu' (TIME ZONE)2026-09-25
enum_typesCREATE TYPE ... AS ENUM: the types and their labels, kept in the catalog2026-09-25
row_ttlWITH (ttl_column = c): rows that expire, kept in the catalog2026-09-25
column_compressionSET (compression = on) on a table and its packed partition files (compression); kdb downgrade writes the files plain again once the table is set to off2026-09-25
calendarsCREATE CALENDAR: trading calendars (eras, holidays, extra trading days), kept in the catalog2026-09-25
materialized_view_sample_bya materialized view over a SAMPLE BY query (QuestDB's form)2026-09-26
commentsCOMMENT ON TABLE / COLUMN: the comments of tables and columns, kept in the catalog; COMMENT ON ... IS NULL removes one2026-09-26
partition_tailstail files (kdb serve --tail-files on): rows appended to a partition saved in extra files next to it; kdb downgrade writes those partitions whole again2026-10-02
partition_deltasdelta files (on unless KDB_NO_PARTITION_DELTA=1): a few rows of a partition replaced, updated or deleted, saved in one extra file next to it; kdb downgrade writes those partitions whole again2026-10-02
compressed_logcompressed log: a big commit's log records written packed (on unless KDB_WAL_COMPRESS=off), so every database this KDB opens has it; kdb downgrade to an older KDB turns packing off by itself while it works2026-10-02
search_analyzerCREATE FULLTEXT INDEX ... WITH (language = 'english'): the word analyzer of a full-text index, kept in the catalog2026-10-02
fulltext_segmentsthe words of full-text and JSON indexes saved in the folder fts/ (segments on disk). Never put in a database's list: an older KDB ignores the folder, so it still opens the database; kdb downgrade to a KDB without it moves the folder's files to _trash2026-10-02
endpointsCREATE ENDPOINT: saved queries served at GET /v/name, kept with the functions and procedures2026-10-03

Two options named late

Two table options were saved for a while as a new part of a table in the catalog, without a feature name. Since 2026-09-25 they have one: symbol_partitions and round_time_zone. KDB adds the name to the list at the next checkpoint.

Table optionSaved asWritten sinceNamed since
a column TIMESTAMP ROUND 1d TIME ZONE 'Asia/Kathmandu'catalog part R2026-09-132026-09-25 (round_time_zone)
PARTITION BY ..., SYMBOL(col)catalog part P2026-09-182026-09-25 (symbol_partitions)

Changes that need no format change

These newer changes write nothing an older KDB cannot read. An older KDB that knows the features in the database's list still opens it.

ChangeSinceWhy the files stay the same
tables without a DEDUP KEY loaded as sorted runs2026-09-23the same run log record (runs) as tables with a key
skipping partitions and blocks by column stats, count/min/max/sum from saved stats2026-09-23partition files already had the stats (block_stats)
table write locks, group commit, reader yield2026-09-23only how writers take turns in memory
keys of dropped tables removed from the manifest2026-09-23fewer keys of a kind the manifest already had. See manifest keys.
indexes built at open2026-09-23indexes are never stored
pinned queries2026-09-23kept as rows of an ordinary table, _pinned_queries (in _system, or in the database of a server without a data folder)