Storage · K3 Tables

Serverless SQL on your bucket.

Serverless HTAP, built in Rust, on every K3 bucket. Run analytical SQL with parallel scans, ACID transactions, and transactional-fresh reads — with no warehouse to run.

my-bucket / contracts.sqlk3 tables
run
-- Analytics · distributed scan, parallel partitions.
SELECT region,
       COUNT(*)      AS cnt,
       SUM(amount)   AS total,
       AVG(amount)   AS avg_value
FROM contracts
WHERE signed_at > '2026-01-01'
GROUP BY region
ORDER BY total DESC;
3 rows · 4 partitions scanned in parallel · 47 ms
region
cnt
total
avg_value
UK
142
£ 8,419,200.00
£ 59,290.14
EU
98
£ 5,724,600.00
£ 58,414.29
US
24
£ 1,442,400.00
£ 60,100.00
Distributed query

Plan once.
Scan partitions in parallel.

The planner opens the Delta target, enumerates partitions, and fans out one Ignite worker per partition. Partial results stream back to a reducer that does sum / count / top-k / welford merges in pure compute.

planner
warehouse_planner
opens Delta · rewrites SQL · fans out
warehouse_query · region=UK3,201
warehouse_query · region=EU4,912
warehouse_query · region=US2,734
warehouse_query · region=APAC2,000
reducer
aggregate_results
sum · top-k · welford
planscan parallel 4 → merge47 ms end-to-end · 12,847 rows aggregated
HTAP

Read-after-write,
without the warehouse.

Writes append to a WAL on S3 — every PUT is a single object, so concurrent writers don't fence each other. A separate compactor drains WAL → Delta in batches. Read with freshness: 'strong' to merge WAL + Delta in the same query — newly-written rows are visible immediately, with no staging or replica lag.

freshness: eventual· Delta only
8 ms
clientwarehouse_queryDelta scan
freshness: strong· WAL ∪ Delta
14 ms
clienthtap_queryWAL overlayDelta scan
Powered by Ignite
Serverless functions — planners, workers, reducers, compactors
warehouse_querywarehouse_insertwarehouse_mergewarehouse_plannerwarehouse_aggregate_resultshtap_upserthtap_compact_tickhtap_query
Time travel — every write is a version

Read the table as it was.

Every INSERT, MERGE and OPTIMIZE creates a new transactional snapshot. Query any version with AS OF VERSION or AS OF TIMESTAMP — or roll the whole table back with one statement.

Versions7 of 1,297
v1297headMERGE
89 rows · mohrizk · 2m ago
v1296INSERT
412 rows · mohrizk · 14m ago
v1295OPTIMIZE
system · 1h ago
v1294INSERT
320 rows · mohrizk · 3h ago
v1293SCHEMA
mohrizk · yesterday
v1292MERGE
67 rows · scriptum · 2d ago
v1291VACUUM
system · 3d ago
Reading @v1294· 2026-05-21 11:42:08 UTCsnapshot frozen
SELECT * FROM contracts AS OF VERSION 1294 WHERE region = 'UK'
id
region
signed_at
amount
9912001
UK
2026-04-01
58,200.00
9912003
UK
2026-04-04
91,400.00
9912005
UK
2026-04-07
67,300.00
3 rows·18 ms·0 files rewrittenΔ HEAD shows 4 rows · row 9912007 added in v1296
Roll back the whole table
RESTORE TABLE contracts TO VERSION 1294;
Atomic · ms-level · still reversible
Connect — the table speaks five wires

Plug it into any app.

Use the Python or TypeScript SDK, the dodil CLI, any Postgres-wire client (Metabase, DBeaver, Grafana, Tableau), or the raw TableService gRPC. Same table, same SQL.

connect.python
from dodil_k3 import Client
 
k3 = Client(region="uk", token=DODIL_TOKEN)
rows = k3.tables("my-bucket").query("""
SELECT region, SUM(amount) AS total
FROM contracts WHERE signed_at > '2026-04-01'
GROUP BY region
""")
 
for r in rows:
print(r.region, r.total)
Installpip install dodil-k3 · 3.10+ · async alsosame auth · same SQL · same table
Patterns — built for four shapes

Four patterns. One engine.

Real-time dashboards, audit trails, ML feature stores, streaming sinks — same table type, same SQL. No separate “OLTP” and “OLAP” stacks.

Real-time dashboards
HTAP freshness wins here.
SELECT region, SUM(amount)
FROM orders
WHERE created_at >
NOW() - INTERVAL '1 hour'
GROUP BY region
live · /sec1,289
Strong read · < 14 ms · live
Audit trail
Append-only + time travel.
INSERT INTO audit (actor, action,
target, at) VALUES (...);
 
-- replay 3 days ago
SELECT * FROM audit
AS OF TIMESTAMP
'2026-05-18T00:00Z'
v1290↑ replay v1294v1297
Immutable · auditable · cheap
ML feature store
Low-latency entity lookup.
SELECT * FROM user_feats
WHERE user_id = $1
 
-- batch warm
MERGE INTO user_feats
USING training_run_47
ON user_id;
lookupuser_id = 47291
· 47289 · feats[256]
· 47290 · feats[256]
47291 · feats[256] · 1.1 ms
· 47292 · feats[256]
1 ms PK lookup · HTAP
CDC sink / streaming ingest
Kafka / Scriptum → table.
MERGE INTO orders AS t
USING staging AS s
ON t.id = s.id
WHEN MATCHED THEN UPDATE
WHEN NOT MATCHED THEN
INSERT
events / sec14,200
kafka━━▸MERGE━━▸orders
Exactly-once · WAL durable
Data browser — Excel-compatible

View any table in the UI. Use Excel formulas.

Every K3 table opens as a full spreadsheet in the browser — sort, filter, conditional formatting, pivots, comments, and Excel-compatible formulas like =SUMIFS, =VLOOKUP, =XLOOKUP running live against the table. No CSV export. No separate “data tool”.

contracts · Q2 2026
live · synced 2s ago
142 rows · 7 visible
D8fx=SUMIFS(amount, region, “UK”)
A · id
B · regionUK
C · signed_at
D · amount
E · channel
1
9912001
UK
2026-04-01
58,200.00
web
2
9912002
EU
2026-04-02
42,100.00
partner
3
9912003
UK
2026-04-04
91,400.00
web
4
9912004
US
2026-04-05
24,800.00
web
5
9912005
UK
2026-04-07
67,300.00
api
6
9912006
EU
2026-04-10
33,750.00
partner
7
9912007
UK
2026-04-12
78,900.00
web
8
UK total
295,800.00
selectionSum295,800.00Count4Avg73,950.00Min58,200.00Max91,400.00region = “UK” · 4 of 7 rows match
FormulasFilters + sortConditional formattingPivot tablesCell commentsNamed ranges
Pricing

Pay per query.
Not per cluster.

Storage at the K3 Objects rate. Compute (planner + workers + reducer) at the Ignite vCPU + GB-RAM rate, charged per second of execution. No idle warehouse.

$0.0199
/ GB · month
Delta files in S3
$0.0432
/ vCPU-hour
Query compute
$0.0060
/ GB-RAM-hour
Query compute
Free
PUT · GET · LIST
no per-request charge
See pricing
Why K3?

Knowledge in three layers.

K3 = Knowledge 3. Tables is the structured-rows layer — extract facts from your objects and query them with SQL, all in the same bucket as the raw files and the embeddings.

01
Objects

Raw bytes. The S3 layer.

02
Tablesyou are here

Rows extracted from those bytes. Delta + DuckDB.

03
Vectors

Embeddings of the same content. Hybrid search.

FAQ

Questions, answered.

A warehouse per bucket.
Without a warehouse.

CREATE TABLE. Run a query. Scale to zero between.

Start free
Regions
UKLiveEULiveMiddle EastSoonAfricaSoon
Compliance
SOC 2In progressISO 27001In progressGDPR-readyData residencyEnforced
© 2026 Circle Technologies Pte Ltd. All rights reserved.