Files
alkstore/docs/architecture/deployment.md
T
glm-5.3-flash 4391f6e879 docs: open Phase 1 — architecture spec set over the Phase 0 evidence
docs/architecture/ now exists: README index, overview, five component
specs (core-contract, engine-sqlite, engine-postgres, queues,
deployment), ADR-001..007 carrying the Phase 0 resolved decisions
(crate split, feature scope, per-engine drivers, dependency
ownership, wake contract, tx seam), and the centralized
open-questions tracker promotion: OQ-ST-01..08 mirror to OQ-01..08
one-to-one with statuses/resolutions carried; new Phase 1 questions
append (OQ-09 scheduler collapse, OQ-10 contract versioning).
Open Phase 1 work: OQ-04 contract pinning (high), OQ-05 queue
semantics depth (high), OQ-06 honker-core quality read (high;
fork-trigger gate), OQ-08 capability surface, OQ-09, OQ-10.

Erratum fixed in phase-0 OQ-ST-04 (thread-affinity friction is
SQLite-side, previously garbled as pg-side) and a stale scheduler-
boundary pointer corrected in consumer-inventory.md. Two review
passes run (findings: OQ-promotion numbering faithfulness, ADR
back-reference sync) — all critical/warning findings resolved.
2026-10-04 18:13:10 +00:00

5.7 KiB
Raw Blame History

status, last_updated
status last_updated
draft 2026-10-04

Deployment

What a deployer must know to size, run, and reason about alkstore engines: host semantics, connection budgets, durability knobs, and where engine differences may honestly surface in the contract. The capability-surface decision (how much of this the trait exposes) is OQ-08's; this document holds the facts and the decision's frame.

Host semantics

Engine Host posture Notes
SQLite single-machine, file-backed NFS two-writers unsupported (honker's honesty posture, inherited, ADR-003). Cross-process on one host is verified POC ground (data_version is cross-process by nature).
Postgres multi-host native Nothing assumes a shared host; POC #2 ran all-through-network (docker bridge) with the same properties (ADR-004).

The unified trait must not pretend SQLite is multi-host — but whether that honesty lives as runtime capability flags, compile-time engine knowledge, or a documented matrix only is OQ-08 (ADR-006 note: the trait's shape constrains where capability differences can surface).

Options for OQ-08, with their shape:

  1. Compile-time only — a consumer chooses an engine crate at dependency time; the engine's docs carry its deployment facts. Smallest contract; nothing runtime to match on.
  2. Store::capabilities() — a runtime description (payload limits, wake cadence knobs, host semantics). Lets a consumer adapt (e.g., chunk large notify payloads) but adds a contract surface all engines must keep honest.
  3. Deployment matrix only (this document) — no API surface. The honest-middle choice; matches the ecosystem's doc-first posture but provides no programmatic guard.

Connection budgets

SQLite engine

  • Connections are in-process (writer + reader pool + watcher thread owning a connection). No external budget lines; the file lock is the OS-level resource.

Postgres engine

Connection class Count Notes
Pool max_size per process claims/queries via deadpool
Listener +1 per LISTEN-ing process non-pooled, dedicated; pooled connections cannot carry LISTEN (deadpool#360, test-pinned — ADR-004)
— — Sizing rule: max_size + 1 per process; verify end-to-end accounting (POC #2's pgdiag-st-4: pool 6 + 1 listener + probe conns = exact server-side count)

Shared-server co-tenancy (the alkblobs ADR-008 precedent — /workspace/@alkdev/alkblobs/docs/architecture/decisions/ — consumer tables co-tenant the pg instance) is supported and expected — the naming / reserved namespace contract protects reserved names; queue/stream/lock tables are schema-named to avoid collisions (layout decision in queues.md, OQ-05's namespace bullet).

Durability knobs

Engine Knob Shape
SQLite synchronous WAL + NORMAL shipped (ADR-003); FULL is available consumer-side for stricter durability; commit fsyncs land at WAL checkpoints (the ~1000-commit spike cadence, POC #1)
Postgres synchronous_commit per-session knob; on is ship config (p50 2.40 ms seam); off trades max-tail (40.9 ms) for slightly better p50 — measured, honest trade (ADR-004); session-level SET mechanics POC-verified

These are engine-configuration concerns, not trait surface (a consumer may set them via their own engine config — what part of engine config is contract-level Store::open shape vs engine-crate docs is OQ-04's config-shape item).

Toolchain / platform notes

Note Engine Affects
rusqlite 0.40.x needs rustc ≥ 1.99 SQLite any binary linking alkstore-sqlite (ADR-003)
bundled-sqlite adds a C build (~10 s dev, cacheable) SQLite build/CI time
libsqlite3-sys collision with sqlx today any mixed-driver binary structurally avoided (ADR-001 single-driver rule)
Listener application_name set for diagnosability (kill-targetable) Postgres ops runbooks (ADR-004)

Consumer-facing latency profile (indicative, POC-measured)

From both POCs (single-box, relative shapes are the deliverable — ADR-003 and ADR-004 carry the full tables):

  • Tx seam: SQLite ~0.35 ms p50; Postgres ~2.4 ms p50 (ship config).
  • Wake: ~1.1–2.2 ms p50 both engines at default cadence.
  • Queue claim: LISTEN-driven 3–6 ms p50 (pg); poll-only interval-bound (32–50 ms at a 50 ms poll).
  • Absolute numbers will differ per hardware/network; they set expectations of order, not SLAs — contract docs must not bake them in (ADR-007's pg-POC note).

Design Decisions

ADR Decision Summary
001 Crate split single-driver binaries shape the matrix
003 SQLite driver bundling, toolchain floor
004 Postgres driver listener budget line, forwarder posture
006 Wake contract where capability differences may surface

Open Questions

Open questions are tracked in open-questions.md. Key questions affecting this document:

  • OQ-08: capability-surface shape — compile-time vs runtime flags vs matrix-only (open)
  • OQ-04: engine-config surface in the contract's Store::open shape (shared) (open)