Files
alkstore/docs/architecture/deployment.md
T
glm-5.3-flash 79a135c934 docs: resolve OQ-05 + OQ-09 — queue semantics depth (ADR-010) and scheduler collapse (ADR-009)
ADR-009: scheduler collapses into queues — schedule()/unschedule()/
run_schedules (opt-in, no ambient timers), @every-only v1 grammar
(dissolves honker's local-TZ cron brittleness), boundary guarantee
row (at-least-once per boundary, fixed 64-cap catch-up with
skip-forward, row-locked fire tx as engine-generic no-double-fire
floor), __alkstore_scheduler leadership lock, InvalidSpec +
LeadershipLost taxonomy additions.

ADR-010: queue depth pinned engine-uniformly — three-state machine
(pending/processing/dead) with delete-on-ack, get_job sees dead rows,
heartbeat = renewal with late-heartbeat refusal, reclaim-consumes-
an-attempt stated as contract text, equal-jitter exponential backoff
(range definitionally pinned, 1 h cap), QueueOpts stamped onto job
rows at enqueue (no per-queue registry), move-to-dead dead-letter
with retention-sweep support and no redrive API, sweep_expired
carries the no-stranded-rows property (fixes honker's expired-
processing zombie hole — SQLite-side realization rides OQ-06 as a
concrete fork candidate), one engine-owned pg schema, queues are
rows not tables, result-storage cut-flag stands.

Also: full honker-machinery and pgboss-rs reference reads persisted
(docs/research/reference-*.md — the honker defect list pre-stages the
OQ-06 quality read), queues.md rewritten from design-space frame to
resolved-depth spec, core-contract/engines/README/overview/deployment/
ADR-002 propagated.
2026-10-05 03:10:52 +00:00

6.0 KiB
Raw Blame History

status, last_updated
status last_updated
draft 2026-10-05

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/schedule tables live in one engine-owned PostgreSQL schema (default alkstore, per-engine option) — layout per ADR-010 §8 (resolved from queues.md'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. What part of engine config is contract-level shape vs engine-crate docs is decided: constructors and option structs live in the engine crates; the contract is the trait the constructor returns (ADR-008 §6).

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
008 Contract v1 constructor/options in engine crates; no capability surface in v1 (OQ-08)

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)