Appearance
Run kinedb
kinedb is one program, kinedb. The same program is a server, a node of a cluster, a SQL shell, and an embedded engine for one-off SQL. This page tells how to start it, and it lists every command-line argument and every environment variable.
Get kinedb
Today the only distribution is a container image. The pull needs no login:
sh
docker pull git.kinedb.com/kinedb/kinedb:latest- Tags.
latest, and one tag per build: the first 12 characters of its git commit. - Content. The static
kinedbbinary at/app/kinedb, and the web console with these docs at/app/dist. The image is built forlinux/amd64. - Defaults. The image runs as the user 65532. Its default command is
--port 4820 --data-dir /data, and/datais a volume.
The binary in the image is static, so you can copy it out and run it on any x86-64 Linux:
sh
id=$(docker create git.kinedb.com/kinedb/kinedb:latest)
docker cp "$id":/app/kinedb ./kinedb
docker rm "$id"One server
sh
docker run -d --name kinedb -p 4820:4820 -v kinedb-data:/data \
-e KINEDB_ROOT_PASSWORD='choose-a-password' \
git.kinedb.com/kinedb/kinedb:latestOr with the binary:
sh
KINEDB_ROOT_PASSWORD='choose-a-password' ./kinedb --port 4820 --data-dir ./data- Without
--data-dir, the data stays in memory, and it is lost when the process stops. - One port carries everything: the clients, the peers, the web console at
/ui/, and these docs at/ui/docs/.
Log in
Clients must log in by default (KINEDB_CLIENT_AUTH=required).
The first boot creates the user root. With KINEDB_ROOT_PASSWORD, root gets that password. Without it, the server makes a password and writes it once to its log:
sh
docker logs kinedb 2>&1 | grep 'GENERATED password'The SQL shell reads the password from KINEDB_ROOT_PASSWORD and logs in as root. Use --user and --password-env for another user. There is no password prompt.
sh
docker exec -it kinedb /app/kinedb --connect 127.0.0.1:4820
docker exec kinedb /app/kinedb --connect 127.0.0.1:4820 -e "SHOW DATABASES"Over HTTP, POST /login gives a token, and every other request carries it:
sh
curl -s -X POST http://localhost:4820/login \
-d '{"username": "root", "password": "choose-a-password"}'
# the answer is a JSON object with a "token"
curl -s -X POST http://localhost:4820/sql \
-H "Authorization: Bearer <token>" \
--data-binary 'SHOW DATABASES'An application uses a client library: JavaScript or Python.
KINEDB_CLIENT_AUTH=permissive turns the login off: then anyone who reaches the port can read and write. Use it only on a network that you trust.
A cluster
A cluster is any number of kinedb nodes. To start one:
- Choose a cluster secret. Give every node the same
KINEDB_CLUSTER_SECRET. Peer authentication is on by default, and a cluster node without a secret refuses to start. - Start the first node with
--calvin. - Start every other node with
--calvin --join <host:port of a running node>. - Set
KINEDB_ADVERTISE_ADDRon every node to the address that the other nodes use to reach it. A node that listens on all interfaces, which includes every container, otherwise tells its peers127.0.0.1.
Three hosts, 10.0.0.1 to 10.0.0.3, with Docker:
sh
# on 10.0.0.1: the first node
docker run -d --name kinedb -p 4820:4820 -v kinedb-data:/data \
-e KINEDB_CLUSTER_SECRET='a-long-random-secret' \
-e KINEDB_ROOT_PASSWORD='choose-a-password' \
-e KINEDB_ADVERTISE_ADDR=10.0.0.1 \
git.kinedb.com/kinedb/kinedb:latest --port 4820 --data-dir /data --calvin
# on 10.0.0.2 (and the same on 10.0.0.3, with its own address)
docker run -d --name kinedb -p 4820:4820 -v kinedb-data:/data \
-e KINEDB_CLUSTER_SECRET='a-long-random-secret' \
-e KINEDB_ROOT_PASSWORD='choose-a-password' \
-e KINEDB_ADVERTISE_ADDR=10.0.0.2 \
git.kinedb.com/kinedb/kinedb:latest --port 4820 --data-dir /data --calvin --join 10.0.0.1:4820Arguments after the image name replace the default command, so they repeat --port and --data-dir.
- Ports. The nodes talk to each other on the same TCP port as the clients. There is no other port to open.
- Replicas. Each shard has 3 replicas by default.
KINEDB_REPLICATION_FACTORsets the first value on a new cluster; after that,SET CLUSTER cluster.replication_factor = <n>changes it. - Joining. A joining node waits 10 seconds for the leader to accept it, and then it exits with an error (
KINEDB_JOINER_BOOT_TIMEOUT_MS). - Durability. A write is durable when the cluster acknowledges it: each replica writes the entry to disk before it counts toward the quorum. Each node keeps its Raft log in
<data-dir>/raft_wal.
Embedded: SQL without a server
With -e or -f and without --connect, kinedb runs the SQL in its own process and exits. No server starts, and no port opens. With --data-dir, the data stays for the next call.
sh
./kinedb --data-dir ./data -e "CREATE TABLE t (id INT, name TEXT, PRIMARY KEY (id))"
./kinedb --data-dir ./data -e "INSERT INTO t (id, name) VALUES (1, 'a'); SELECT * FROM t"
./kinedb --data-dir ./data -f setup.sql-esplits the SQL on;and runs the statements in order.-f file.sqldoes the same with a file, and-f file.kdruns a kd script.-estops at the first statement that fails. It prints a line that starts withERROR:, and it exits with 1.- Some statements need a server; the SQL reference marks them.
In Rust, the kinedb crate is the same engine as a library (Db::open(path), db.execute(sql)).
Command-line arguments
| Argument | Default | What it does |
|---|---|---|
--port PORT | 4820 | The TCP port for the clients, the peers, the web console and these docs. |
--data-dir DIR | not set | The directory of the data. Without it, the data stays in memory. |
--memory SIZE | not set | The total memory budget of the process, for example 4GB or 3800MB. kinedb enforces it with its own accounting. It needs --data-dir, and it does not work with --s3 or --connect. |
--cache-slab SIZE | not set | A block cache that is allocated at start. Under --memory, it must fit the budget. Alone, it is the older way to size the cache. |
--gc-retention SPEC | not set | Turns on the garbage collection of dead blocks, and sets the history to keep: <N>commits (the head and N older commits; 0commits keeps only the head) or <N>s, <N>m, <N>h, <N>d (for example 7d). Without it, nothing is reclaimed. |
--calvin | off | Cluster mode: Raft and the deterministic sequencer. Every node of a cluster needs it. |
--join HOST:PORT | not set | Join a cluster through a running node. Use it with --calvin. |
--peer-auth MODE | required | required: the nodes must prove that they know the cluster secret. permissive: they need not. |
--cluster-key KEY | kinedb | The name of the cluster. A node ignores the gossip of a node with another key. It is not a secret. |
--realm NAME | not set | The realm of the node. Leave it unset for one realm. |
--s3 URI | not set | Store the blocks in S3: s3://KEY:SECRET@HOST/BUCKET/PREFIX?region=R. --data-dir is then the local cache; without it, a temporary directory. |
--webroot DIR | found | The directory of the web console. Without it, kinedb looks for dist next to the binary, then for dist and web/dist in the working directory. |
--no-web | off | Serve no web console and no docs. |
--connect HOST:PORT, -c | not set | Client mode: open a SQL shell on a running server, or run -e or -f there. |
--user NAME | root | Client mode: the user to log in as. |
--password-env VAR | KINEDB_ROOT_PASSWORD | Client mode: the environment variable that holds the password. |
-e SQL | not set | Run SQL and exit. Without --connect, the SQL runs in this process. |
-f FILE | not set | Run a file and exit: .kd is a kd script; any other file is SQL. |
--show-types | off | Client mode: put the column type in the header of a result, for example price:Float. |
--help, -h | Print the usage and exit. |
Environment variables
Setup
| Variable | Default | What it does |
|---|---|---|
KINEDB_ROOT_PASSWORD | not set | The password of root, set at the first boot. Without it, the first boot makes a password and logs it once. The SQL shell also reads it to log in. |
KINEDB_CLIENT_AUTH | required | required: clients must log in. permissive: anyone can query. |
KINEDB_PEER_AUTH | required | The same as --peer-auth. The flag wins. |
KINEDB_CLUSTER_SECRET | not set | The secret that the nodes of a cluster share. It is only an environment variable, so it does not show in a process list. |
KINEDB_ADVERTISE_ADDR | not set | The address that the peers use to reach this node, host or host:port (the port part is ignored). Without it, a node that listens on all interfaces advertises 127.0.0.1. |
KINEDB_GC_RETENTION | not set | The same as --gc-retention. The flag wins. |
KINEDB_RAFT_WAL_DIR | <data-dir>/raft_wal | The directory of the Raft logs. Without a data directory and without this variable, the Raft log stays in memory. |
KINEDB_LOG_SINK | not set | ws://host:port of a kinedb server that collects logs and metrics. With it, the node sends its logs and metrics there. |
KINEDB_LOG_SINK_USER, KINEDB_LOG_SINK_PASSWORD | not set | The login at the log sink. |
Tuning
These variables belong to the settings of the server; SHOW SETTINGS lists the same settings with the values in force. A variable of a cluster. setting sets the first value on a new cluster; after that, SET CLUSTER <setting> = <value> changes it. A node reads the variable of a node. setting when it starts.
| Variable | Setting | Default | What it does |
|---|---|---|---|
KINEDB_CALVIN_APPLY_TIMEOUT_SECS | cluster.calvin.apply_timeout_secs | 60 secs | How long a Calvin write waits for local apply before returning an error. |
KINEDB_SEQUENCER_BATCH_AGE_MS | cluster.calvin.sequencer_batch_age_ms | 2 ms | Maximum age (ms) a sequencer batch waits before flushing. |
KINEDB_SEQUENCER_BATCH_SIZE | cluster.calvin.sequencer_batch_size | 1024 | Maximum number of operations in a single Calvin sequencer batch. |
KINEDB_FORCE_QUORUM | cluster.quorum | not set | Recovery only: forces cluster.quorum on this node for the life of the process. |
KINEDB_REPLICATION_FACTOR | cluster.replication_factor | 3 | Number of Raft voter replicas per shard (RF<N mode). |
KINEDB_FORCE_REPLICATION_FACTOR | cluster.replication_factor | not set | Recovery only: forces cluster.replication_factor on this node for the life of the process. |
KINEDB_SPLIT_COOLDOWN_SECS | cluster.split.cooldown_secs | 60 secs | How long (secs) after a successful split before the same shard can be split again. |
KINEDB_SPLIT_INTERVAL_MS | cluster.split.interval_ms | 10000 ms | How often (ms) the SplitManager wakes to check if any shard has crossed the split threshold. |
KINEDB_SPLIT_MAX_CONCURRENT_APPLIES | cluster.split.max_concurrent_applies | 2 | How many split applies this node may have in flight at once. |
KINEDB_MAX_SHARDS | cluster.split.max_shards | 256 | Global cap on the total number of shards. |
KINEDB_SPLIT_THRESHOLD_BYTES | cluster.split.threshold_bytes | 67108864 bytes (64 MiB) | Shard size (bytes) at which the SplitManager proposes an automatic split. |
KINEDB_FLUSH_GENERATION_BYTES | cluster.storage.flush_generation_max_bytes | 67108864 bytes (64 MiB) | Payload-byte bound on ONE flush generation. |
KINEDB_FLUSH_GENERATION_KEYS | cluster.storage.flush_generation_max_keys | 512000 | Key-count bound on ONE flush generation, the companion to flush_generation_max_bytes — tree-mutate cost tracks KEYS while block-write cost tracks BYTES, and neither rate alone predicts cycle time across row shapes, so both are checked and whichever binds first rotates. |
KINEDB_PER_SHARD_MEMTABLE_BYTES_LIMIT | cluster.storage.memtable_max_bytes | 268435456 bytes (256 MiB) | Per-shard memtable byte cap. |
KINEDB_SEQUENCER_PENDING_BYTES_LIMIT | cluster.calvin.sequencer_pending_bytes_limit | 536870912 bytes (512 MiB) | Per-shard Calvin sequencer staging-buffer byte cap. |
KINEDB_RAFT_LOG_PENDING_BYTES_LIMIT | cluster.calvin.raft_log_pending_bytes_limit | 536870912 bytes (512 MiB) | Per-shard cap on bytes the leader has proposed but not yet replicated to min(match_index) across peers. |
KINEDB_RAFT_LOG_COMPACTION_BYTES | cluster.calvin.raft_log_compaction_bytes | 67108864 bytes (64 MiB) | Per-shard byte budget for the byte-aware raft-log compaction trigger. |
KINEDB_RAFT_LOG_MARGIN_BYTES | cluster.calvin.raft_log_margin_bytes | 4194304 bytes (4 MiB) | Byte budget for the raft-log compaction SAFETY MARGIN — the trailing band each shard holds ABOVE effective_floor so a briefly lagging peer can still be served by AE retransmit. |
KINEDB_RAFT_LOG_COMPACTION_NODE_BYTES | cluster.calvin.raft_log_compaction_node_bytes | 536870912 bytes (512 MiB) | Node-wide ceiling on the sum of every local shard's retained raft-log body. |
KINEDB_PEER_BROADCAST_QUEUE_BYTES_LIMIT | cluster.calvin.peer_broadcast_queue_bytes_limit | 1073741824 bytes (1 GiB) | Per-peer outbound broadcast-queue byte cap. |
KINE_DIAG | node.diag.diag | false | Enable diagnostic logging mode (presence of KINE_DIAG enables). |
KINE_TRANSFER_LOG | node.diag.transfer_log | false | Enable verbose logging of shard transfer operations (KINE_TRANSFER_LOG). |
KINEDB_RAFT_ELECTION_US | node.raft.election_us | 5000000 us | Raft election timeout in microseconds. |
KINEDB_RAFT_HEARTBEAT_US | node.raft.heartbeat_us | 500000 us | Raft leader heartbeat interval in microseconds. |
KINEDB_JOINER_BOOT_TIMEOUT_MS | node.raft.joiner_boot_timeout_ms | 10000 ms | How long (ms) a joining node waits to receive its first AppendEntries before giving up and exiting with an error. |
KINEDB_JOIN_PIN_BUDGET_MS | node.raft.join_pin_budget_ms | 60000 ms | How long (ms) a shard leader holds the Raft-log compaction floor pinned for a reserved joiner. |
KINEDB_JOIN_PIN_WAIT_MS | node.raft.join_pin_wait_ms | 5000 ms | How long (ms) ONE shard acquisition waits for a peer that can serve a snapshot at or above the reserved pin. |
KINEDB_RAFT_SWIM_POLL_MS | node.raft.swim_poll_ms | 500 ms | How often (ms) the Raft membership observer polls SWIM state to detect peer additions and removals. |
The server reads more KINEDB_* variables for diagnostics, tests and recovery. They are not a stable interface, and this page does not list them.
Ports and endpoints
Everything uses one TCP port, 4820 by default.
| Path | What it is |
|---|---|
GET /health | Health check. It needs no login. |
POST /login | {"username": ..., "password": ...} in, a token out. |
POST /sql | SQL text in, JSON out. Send Authorization: Bearer <token>. |
/ws | A WebSocket with the binary protocol of the client libraries. Live queries (WATCH) use it. |
/ui/ | The web console. |
/ui/docs/ | These docs, for the version of this node. /ui/docs/llms-full.txt holds all pages in one file. |