Skip to main content

Quick Start

1. Start the server

xcon-db-server -sample-config > xcon-db.toml
# edit xcon-db.toml: set root, listen addresses and the [admin] password
xcon-db-server -config xcon-db.toml

The [admin] user in the config file always exists — that is the whole bootstrap (the postgres/sa pattern).

2. Create a database and a user

Every tenant is one database — one self-contained directory. Connect as the admin and build it over SQL:

psql "postgres://xcon:change-me@127.0.0.1:5432/xcon"
CREATE DATABASE demo;
CREATE USER demo PASSWORD 'secret' DATABASE demo;

3. Create a table

Any PostgreSQL client works. With psql:

psql "postgres://demo:secret@127.0.0.1:5432/demo"
CREATE TABLE telemetry (
speed DOUBLE FILL HOLD STALENESS 60 s,
event TEXT FILL NONE
) WITH (RETENTION 90 d);

entity (which device) and ts (Unix milliseconds) are implicit columns on every table.

4. Write and read

INSERT INTO telemetry (entity, ts, speed) VALUES
('veh-1', 1700000000000, 50),
('veh-1', 1700000060000, 62);

INSERT INTO telemetry (entity, ts, event) VALUES
('veh-1', 1700000030000, 'brake');

SELECT * FROM telemetry WHERE entity = 'veh-1';

Note what comes back: at ts = 1700000030000 the speed column reads 50 — the last observed value, carried forward because the channel was declared FILL HOLD. The event column is null everywhere except its exact timestamps, because FILL NONE refuses to invent data. This is forward-fill, the heart of the read model.

5. Or ingest over ILP

# InfluxDB line protocol, straight from a device or Telegraf
# (config: listen.ilp = ":9009", listen.ilp_db = "demo"):
printf 'telemetry,entity=veh-1 speed=52.5 1700000120000000000\n' \
| nc 127.0.0.1 9009