# Dux > Dux is a sync stack: apps write SQLite on the device, changes reach PostgreSQL, and every row version lands in a lake you query with DuckDB. Dux is an open source sync stack. Apps read and write SQLite on the device, changes merge into PostgreSQL, and every committed row version lands in [DuckLake](https://ducklake.select) for `dux sql`. Built in Rust by [linesofcode](https://x.com/linesofcode). ## Offline-first sync Run `dux dev` in a project and it compiles `dux.schema`, starts PostgreSQL on a free port and serves sync. Devices write SQLite offline; buckets and write rules decide what each user sees and may change. [M1 commands](https://github.com/TimMikeladze/dux/blob/main/docs/m1-status.md). ```sh cargo run -- init /tmp/dux-app cd /tmp/dux-app /path/to/dux/target/debug/dux dev # Compiles dux.schema, starts PostgreSQL in .dux/postgres on a free port (or uses # DUX_DATABASE_URL), serves sync on 127.0.0.1:8080 (or a free port if taken) and # writes .dux-dev.json (endpoint, token, inspector URL, database URL). # Inspector: /dev/inspector. Extra users: GET /dev/token?user=NAME. # Attachments: set DUX_S3_ENDPOINT, DUX_S3_ACCESS_KEY, DUX_S3_SECRET_KEY # (optional DUX_S3_BUCKET, DUX_S3_REGION, DUX_BLOB_DIR) to mount /blob. # Analytics lake (docs/p1.md): dux dev runs one in .dux/lake (SQLite catalog, # 2 s flush); dux serve opts in with --lake sqlite|postgres|files. # Stream tables (docs/p2.md): POST /ingest appends; rollups run after each # flush (1 s in dev); retention every --retention-secs (60 s in dev), which also # expires DuckLake snapshots older than --lake-snapshot-days. `dux sql` includes # rows still in the stream log. # Streams need `write insert: `. `dux dev --no-postgres` serves streams, rollups and # /query over the lake alone (no sync). # Production: configure issuer, audience and HTTPS JWKS instead. /path/to/dux/target/debug/dux sql "SELECT lane_id, count(*) FROM cards GROUP BY 1" /path/to/dux/target/debug/dux lake ingest visits visits.csv /path/to/dux/target/debug/dux serve --issuer https://issuer.example --audience dux --jwks-url https://issuer.example/jwks.json --cors-origin https://app.example # Without --database-url, serve streams and /query only: add --lake files|sqlite. ``` ## Replay any failure The simulator drives three clients through dropped acks, partitions, crashes and clock jumps. Pass `--seed` and `--steps`; the same pair reproduces the same trace and state hash. ```console $ cargo run -- simulate --seed 7 --steps 1000 seed=7 steps=1000 accepted=23 rejected=159 events=1326 state_hash=4fbadd1bf0e4a38f converged=true ``` ## Streams without the wait Append-only rows go to `POST /ingest` or the client outbox and are acknowledged after fsync. Watermarked rollups can sync back to devices. [P2 evidence](https://github.com/TimMikeladze/dux/blob/main/docs/p2.md). | Producers × rows per batch | Accepted rows/s | Ack p50 | Ack p99 | Notes | |---|---|---|---|---| | 2 × 500 | 148,000 | 5.8 ms | 12.6 ms | flush keeps up (86k rows left at the end) | | 4 × 500 | 286,000 | 5.8 ms | 12.9 ms | flush keeps up | | 16 × 1,000 | 560,000 | 7.0 ms | 11.2 ms | flush-bound: 4,176 busy (503) replies, backlog held at 2M rows | ## Speaks Postgres `--pg-listen` serves the Postgres wire protocol, so `psql` and Grafana connect without a plugin. Timescale-style hyperfunctions like `time_bucket_gapfill` work as-is. [Grafana walkthrough](https://github.com/TimMikeladze/dux/blob/main/docs/grafana.md). ```sql SELECT time_bucket_gapfill('2 minutes', ts) AS time, locf(approx_percentile(0.95, percentile_agg(value))) AS p95 FROM metrics WHERE $__timeFilter(ts) GROUP BY 1 ORDER BY 1 ``` ## Run code next to the data Put DAGs and workflows in `compute/` and ship them with `dux deploy`. Outputs land exactly once in stream, lake or synced tables. [P9 status](https://github.com/TimMikeladze/dux/blob/main/docs/p9.md). ```bash dux dev --no-postgres --lake sqlite # compute is on; python3 / bun run steps locally mkdir compute && $EDITOR compute/sensors.yaml dux deploy # bundles compute/, validates, activates dux runs ls # the ledger ``` ## Docs - [Reference](https://dux.sh/reference): the README in full - [AGENTS.md](https://dux.sh/AGENTS.md): how an agent should use Dux - [Repository](https://github.com/TimMikeladze/dux) - [Benchmarks](https://github.com/TimMikeladze/dux/blob/main/docs/benchmarks/tsbs.md)