6.1 KiB
status, last_updated
| status | last_updated |
|---|---|
| draft | 2026-10-06 |
alkstore — Overview
One reactive store interface over SQLite and Postgres: durable
notify/subscribe signals, streams with per-consumer offsets, durable
queues with the transactional enqueue property, named locks, a
scheduler, and an outbox helper — with each engine using its own
native machinery underneath (SQLite: honker's watcher design;
Postgres: pg_notify/LISTEN and the pg-boss schema family).
Why this crate exists
The alk* ecosystem's current shape is a repository pattern with a default in-memory adapter, cache-invalidation wiring in hot paths, and per-project approximations where a durable reactive substrate was needed. alkblobs paused partly on that fuzziness. alkstore is the substrate, made once: the answer to "how does a change in the database become visible to other processes/connections?" that downstream stores don't re-derive.
Crate family
Per ADR-001:
| Crate | Contents | Driver dependencies |
|---|---|---|
alkstore (core) |
trait surface, types, error model | none (no capability surface — ADR-016: engine differences are compile-time identity + the deployment matrix, never a runtime descriptor) |
alkstore-sqlite |
SQLite engine (ADR-003) | rusqlite; the forked honker-core lineage rides in-tree as the engine crate's substrate module subtree (ADR-011, designed in ADR-012, folded per ADR-013) |
alkstore-postgres |
Postgres engine (ADR-004) | tokio-postgres, deadpool-postgres |
| (mem engine, optional) | test convenience, decided at implementation (ADR-001) | none |
Downstream consumers depend on core + exactly one engine. Family
standards apply throughout: tokio async runtime, thiserror errors, no
panics in library code, no unwrap()/expect() outside tests,
lean base crate.
Feature surface
Per ADR-002:
- First-class: notify/listen; streams.
- In scope: named locks; queues + outbox helper; scheduler.
- Cut-flag: rate limits; result storage.
- Out: loadable-extension surface; DAGs/task chains/chords/multi-writer replication/cross-machine locking.
Document map
| Doc | Purpose |
|---|---|
| core-contract.md | The unified trait surface: mechanisms, delivery guarantees, tx seam, naming |
| engine-sqlite.md | SQLite engine: mapping the contract onto the forked substrate module/rusqlite |
| engine-postgres.md | Postgres engine: mapping the contract onto tokio-postgres/LISTEN |
| queues.md | Queue/scheduler/outbox semantics depth (ADR-009/ADR-010 resolved) |
| deployment.md | Host capabilities, connection budgets, deployment matrix (OQ-08 resolved) |
| open-questions.md | OQ-01..NN tracker |
| decisions/ | ADRs |
What is decided (ADR index)
| ADR | Decision | Status |
|---|---|---|
| 001 | Reactive-core + per-engine crates | Accepted |
| 002 | Feature scope (inventory-confirmed) | Accepted |
| 003 | SQLite: rusqlite + honker-core lineage, bridged seam (ownership: ADR-011) | Accepted |
| 004 | Postgres: tokio-postgres + deadpool, hand-rolled LISTEN | Accepted |
| 005 | Published libraries by default, named fork triggers | Accepted |
| 006 | Opaque wake + re-read; notify-vs-streams guarantee split | Accepted |
| 007 | Caller-held TxHandle with *_tx methods |
Accepted |
| 008 | Contract v1 surface pinning (partition, TxHandle shape, wake type, reserved strings, error taxonomy) | Accepted |
| 009 | Scheduler collapse (queues + schedule(), @every-only) |
Accepted |
| 010 | Queue semantics depth (visibility, backoff, dead-letter, sweep, layout) | Accepted |
| 011 | SQLite substrate — fork honker-core into owned code | Accepted |
| 012 | Forked substrate design (contract-blind boundary, fidelity, port deltas) | Accepted |
| 013 | Fold the forked substrate into alkstore-sqlite (no fourth crate) |
Accepted |
| 014 | Transactional outbox enqueue (outbox_enqueue_tx on TxHandle) |
Accepted |
| 015 | Streams depth (carried-metadata keys, global-FIFO ordering, StreamEvent, trim_to) |
Accepted |
| 016 | Deployment honesty (no runtime capability surface; compile-time identity + matrix) | Accepted |
Non-goals
- Not a database abstraction/ORM: the store covers the reactive coordination surface, not general row storage (consumers keep their own engines/schema for business data, sharing the connection when appropriate — the outbox pattern).
- Not a network service: no transport; any networked ops surface rides alkcall and is a separate future decision (store layer stays substrate-free, the alkblobs store-layer precedent).
- Not multi-machine on SQLite: single-host honesty is inherited (deployment.md; the boundary's location in the surface is decided — ADR-016).
Evidence base
Phase 0 (docs/research/phase-0.md) is complete: two POCs
(poc-sqlite-posture-findings.md, poc-pg-posture-findings.md) passed
all gate conditions; the consumer inventory
(consumer-inventory.md) graded every feature row. The Phase 1
architecture work runs over that complete evidence base; open Phase 1
work is tracked in open-questions.md.