Skip to Content
We are live but in Staging 🎉
Data EnginesSQLOverview

Tables

K3’s table primitive is an HTAP store: a transactional write-ahead log in front of a Delta Lake warehouse, per bucket. Writes append to the WAL, keyed by primary key; an asynchronous compactor drains the WAL into the table’s Delta commit history. Reads are served from whichever tier can answer truthfully — a plain Delta scan when the backlog is provably drained, an overlay ∪ Delta merge otherwise.

That two-lane split is real machinery, not a positioning line: the planner emits an explicit tier for every statement (Oltp, Warehouse, Merged) and the reader builds the overlay view (dodil-tables/crates/htap-planner/, dodil-tables/crates/overlay-view/). What it buys you is that you don’t choose a lane — you write SQL, and the plane picks.

The on-disk format is Delta Lake — open, standard, and time-travel-capable, living in your own bucket. The SQL surface is DuckDB-flavored.

Speak Postgres to it. The data plane exposes a Postgres wire adapter at pg.uk-lon-1.dodil.io:5432 — psql, psycopg, pgx, SQLAlchemy, Django and Prisma connect with the bucket as the database name and sslmode=require (the wire terminates TLS; don’t downgrade to prefer). There’s also gRPC (table-rpc.uk-lon-1.dodil.io:443) and GraphQL (gql.uk-lon-1.dodil.io/graphql). See Connect & wire adapters.

Nothing to enable

Tables are implicit per bucket. There is no engine to provision, no capability to switch on, no lifecycle call before your first CREATE TABLE. Create the bucket, connect, write SQL. Dedicated capacity — if you want it — is a separate, explicit thing: see Capacity.

What you can do

  • Create tables with composite primary keys, partitioning, JSON, DECIMAL, array, struct and VECTOR(N) columns — fifteen types in all
  • Run full SQL through one Execute RPC — SELECT / INSERT / UPDATE / DELETE / MERGE / CREATE TABLE / CTAS / DROP TABLE / ALTER TABLE / CREATE INDEX / SHOW / DESCRIBE / EXPLAIN
  • Use real transactions on the Postgres wire — BEGIN / COMMIT / ROLLBACK, savepoints, prepared statements, server-side cursors, COPY … FROM STDIN and statement_timeout
  • Alter a table in place — multiple ADD COLUMNs, logical DROP COLUMN, and widening-only ALTER COLUMN SET DATA TYPE, mixable in one statement
  • Time-travel — SELECT … VERSION AS OF n, and RESTORE TABLE t TO VERSION AS OF n
  • Auto-extract rows from objects — bind a table to a Scriptum analytics template; rows materialize as documents land in the bucket (see Pipelines)
  • Maintenance — OptimizeTable (bin-pack / z-order), VacuumTable (expire versions past a 168 h floor), Compact (force the WAL drain)

Reads are read-your-writes

There is no freshness knob. A Freshness field a client sends is ignored, and dodil data table query --freshness is a deprecated no-op that prints a notice. Instead the coordinator runs a frontier check before each read: only when the writer proves the WAL backlog is empty does the read take the analytical fast path, because only then is eventual ≡ strong. A strong read that would be incomplete aborts with FAILED_PRECONDITION rather than returning partial truth.

If you need an explicit handle, every write returns a ULID watermark (max_wal_ulid); pass it as the next read’s min_ulid.

Two creation modes

ModeHowWhen to use
ManualCREATE TABLE … via Execute, dodil data table create, or the typed CreateTable RPCYou know the schema. Define columns / partitions / primary key; the Delta table is created eagerly. SQL-first thereafter.
Pipeline-boundCreateTablePipeline, or dodil data table pipeline create -t <template>Unstructured documents land in the bucket and you want them auto-extracted. Pick a warehouse-compatible Scriptum template; schema materializes lazily on first ingest.

Creating a pipeline does not start ingesting. CreateTablePipeline binds the template to a table; it does not create an ingest rule. Scoping a rule at the pipeline is a separate, mandatory step. dodil data recipe install is the exception — it binds the rule for you.

In this section

  • Quickstart — first table, first rows, first query — 5 minutes, in SQL
  • Core Concepts — the WAL/Delta split, the frontier check, write routing, watermarks, ServedBy
  • SQL Compatibility — DuckDB dialect, the fifteen types, statement shapes, the honest refusal list, JSON ops
  • API Reference — the real dodil.tables.v1 surface — Tables · Data · Execute · Maintenance · Templates
  • CLI Guidedodil data sql · dodil data pg · dodil data table
  • Recipes — manual table, pipeline-bound table, time-travel + restore, CTAS

See also

  • Object Storage — where every table’s Delta artifacts live, in your bucket
  • Pipelines — the bridge from unstructured uploads to structured rows
  • Capacity — reservations and residency
  • Conventions — auth, headers, error envelope