KDB knowledge

How KDB stores data

A short tour of the files in a KDB database folder - data files, blocks and checksums, the log, the manifest and backups.

This page explains, in simple words, what KDB writes to the disk and why. You do not need it to use KDB. It helps to understand kdb info, kdb check and the messages about damage. The exact bytes, for developers, are in docs/FORMAT.md. When that file and the code disagree, the code is right.

Do not change or delete files in a database folder by hand. Use kdb commands. To copy a database, stop every program that uses it, or better use kdb backup.

The format is the same on Windows, Linux and macOS, so a database folder can move between them.

The database folder

Syntax:

<database>/
  kdb.lock                   locked while a program has the database open
  _manifest.a  _manifest.b   the list of current files, saved twice
  files/                     data files: files/<name>.v<version>.kdb
  wal/                       the write-ahead log (the newest changes)
  wal_archive/               older log files, kept for backups and repairs
  _trash/                    files taken out of use, deleted after 24 hours

A database is one folder. In a data folder, each database is a sub-folder, plus _trash (dropped databases) and _system (the server's users).

NameWhat it is
kdb.lockAn empty file. While a program has the database open, the operating system locks it, so a second program gets the database is open in another program. Do not delete it: when no program runs, the lock is free anyway.
_manifest.a, _manifest.bThe manifest: the list of the current data files, their versions, sizes and checksums, and the log positions. Two copies (see manifest).
files/The data files: files/catalog.v6.kdb (the list of tables and columns) and files/t/<table number>/<partition>.v<version>.kdb (the rows of one partition). A table split by symbol adds the symbol to the partition name, as hex: 2026-09/s-43495459 is month 2026-09, symbol CITY.
wal/The write-ahead log (WAL): every change is written here first (see the log).
wal_archive/Old log files that the data files no longer need. Only backups and repairs use them. The oldest are deleted when this folder is over its limit: 1 GB by default, changed with ALTER DATABASE ... SET WAL_ARCHIVE or on the Settings page.
_trash/Files taken out of use: old versions, damaged files moved away by a repair, unknown files. Folders older than 24 hours are deleted when the database opens.

Command line: kdb info lists what the manifest says (sample data: sample)

kdb info market

Output:

database        market
manifest        copy a, sequence 9
last shutdown   clean
log position    30 (saved in files up to 30)
newest change   2026-10-22 11:28:27
features        batched_log_sync, block_stats, compressed_log, partition_format_2
manifest keys   26

FILE                                      VERSION       SIZE          LSN  STATUS
catalog                                         6     2.1 KB           30  ok
t/1/all                                         7      777 B           30  ok
t/2/all                                         8      556 B           30  ok
t/3/2025                                        9     1.7 KB           30  ok
t/3/2026                                       10     3.6 KB           30  ok
t/4/2026-09                                    11    57.0 KB           30  ok
t/5/2026-09-09                                 12     1.4 KB           30  ok
t/5/2026-09-10                                 13     2.4 KB           30  ok
t/6/2026-09-10                                 14     2.7 KB           30  ok

9 files, 72.1 KB, 0 marked damaged
(STATUS is what the manifest records. To read every block and find new damage, run: kdb check)

t/4/2026-09 is table number 4 (tables are numbered in the order they were made; here ochl_minutes), partition 2026-09. all is a table without partitions. VERSION 11 is the file files/t/4/2026-09.v11.kdb.

Data files are never changed

Syntax:

files/t/<table number>/<partition>.v<version>.kdb

A data file is written once and then never changed (this is called copy-on-write).

  1. Changes first go into the log and into memory.
  2. From time to time (a checkpoint), KDB writes a new version of each changed partition: a new file with the next version number.
  3. KDB reads the new file back and checks it.
  4. Only then it saves the manifest, which now names the new version.

Command line: One data file: the table securities (sample data: sample)

kdb dump-file market/files/t/1/all.v7.kdb

Output:

file         market/files/t/1/all.v7.kdb
type         data file
version      1
data         693 B
block size   65536
LSN          30
id           1
created      2026-10-22 11:28:27
blocks       1
digest       1d198644
OK: all blocks match their checksums

Blocks and CRC32C checksums

Syntax:

[ header 64 bytes ][ block 1 ][ block 2 ] ... [ checksum table ][ trailer 16 bytes ]

Every KDB file (data files, manifests, backup.kdb) is cut into blocks of 64 KB. Each block has a CRC32C checksum: a 4-byte number made from the bytes of the block.

Command line: Check every block of one file (sample data: sample)

kdb dump-file market/_manifest.a

Output:

file         market/_manifest.a
type         manifest
version      1
data         2.3 KB
block size   65536
LSN          30
id           9
created      2026-10-22 11:28:27
blocks       1
digest       35a9d31d
OK: all blocks match their checksums

The write-ahead log (WAL)

Syntax:

wal/00000000000000000001.log      a log file (segment), named after its first LSN
record: length | checksum | LSN | transaction id | type (data or commit) | data

Every change is first written to the log, and the log is on the disk before KDB says a statement is done.

The manifest: two copies

Syntax:

_manifest.a   _manifest.b    the newer valid copy (highest sequence number) wins

The manifest is the list of what is current: every data file with its version, size, digest and log position, the previous versions, which files are marked damaged, and whether the last shutdown was clean.

Manifest keys

Besides the file list, the manifest keeps small keys for the tables:

KeyWhat it holds
rows.<file>the row count of a partition file
sym.<file>which symbols a partition file holds, so a WHERE symbol = ... skips files without opening them
rowid.<table number>, auto.<table number>the next row id and the next AUTO value of a table

Command line: Which copy is newest (sample data: sample)

kdb info market
kdb dump-file market/_manifest.b

Output:

> kdb info market

database        market
manifest        copy a, sequence 9
last shutdown   clean
log position    30 (saved in files up to 30)
newest change   2026-10-22 11:28:27
features        batched_log_sync, block_stats, compressed_log, partition_format_2
manifest keys   26

FILE                                      VERSION       SIZE          LSN  STATUS
catalog                                         6     2.1 KB           30  ok
t/1/all                                         7      777 B           30  ok
t/2/all                                         8      556 B           30  ok
t/3/2025                                        9     1.7 KB           30  ok
t/3/2026                                       10     3.6 KB           30  ok
t/4/2026-09                                    11    57.0 KB           30  ok
t/5/2026-09-09                                 12     1.4 KB           30  ok
t/5/2026-09-10                                 13     2.4 KB           30  ok
t/6/2026-09-10                                 14     2.7 KB           30  ok

9 files, 72.1 KB, 0 marked damaged
(STATUS is what the manifest records. To read every block and find new damage, run: kdb check)

> kdb dump-file market/_manifest.b

file         market/_manifest.b
type         manifest
version      1
data         2.3 KB
block size   65536
LSN          30
id           8
created      2026-10-22 11:28:27
blocks       1
digest       fe6eb549
OK: all blocks match their checksums

In the header of a manifest, id is its sequence number. The copy that kdb info names has the higher one; the other copy is one save older.

Backup folders

Syntax:

<backups-dir>/
  20260911-161530-123/          a backup; the name is the UTC time
    backup.kdb                  the list of the backup, written last
    files/<name>.v<N>.kdb       the current version of every data file
    wal/<first LSN>.log         the log files needed to replay from those files
  20260912-...-.partial/        an unfinished backup: never used, removed later

Command line: A backup, and its list (sample data: sample)

kdb backup market backups
kdb backups backups

Output:

> kdb backup market backups

backup created and verified: backups/20261022-054330-179
  9 files, 190.0 KB, log up to 30

> kdb backups backups

BACKUP                 CREATED               FILES       SIZE      LOG LSN
20261022-054330-179    2026-10-22 11:28:30       9   190.0 KB           30
1 backups

Indexes are not stored

Syntax:

CREATE INDEX ...     only the definition is saved (in the catalog)

For CREATE INDEX, KDB saves only the definition in the catalog. The index itself lives in memory. It is built from the rows after the database opens: kdb serve builds every index on a background thread right after the open, and a query that needs one before that builds it itself.

Example: An index on a sample table: only its definition is saved (sample data: sample)

CREATE INDEX trade_log_buyer ON trade_log (buyer);
SHOW INDEXES;

Result:

CREATE INDEX trade_log_buyer ON trade_log (buyer)

index 'trade_log_buyer' created on table 'trade_log' (32 rows)

SHOW INDEXES

name (STRING)table (STRING)kind (STRING)columns (STRING)built (BOOL)rows (LONG)memory_bytes (LONG)create_sql (STRING)building (BOOL)
trade_log_buyertrade_logINDEXbuyertrue321777CREATE INDEX trade_log_buyer ON trade_log (buyer)false

(1 row)