Model Coordination And Valkey

Purpose

The backend can run against one Ollama host or a small cluster of AI boxes. Once multiple API workers or model boxes are involved, process-local admission is not enough: each process would only see its own in-flight work and could overcommit the same model hosts.

Valkey provides the shared coordination plane for this problem. It is not the document source of truth, not the retrieval index, and not a replacement for OpenSearch. It exists to make short-lived scheduling decisions visible to every backend process.

Boundary

The runtime storage responsibilities are intentionally split:

Store

Responsibility

JSON document records

Current source truth for document aggregates and answer/query records

Environment-local OpenSearch

Retrieval indexes, catalog/profile/summary projections, ingestion jobs, conversation memory, and projection-control manifests

Environment-local application Valkey

Application coordination and fail-open planning/retrieval caches for one deployment only

Shared model-coordination Valkey

Model placement, monitor election, fenced node residency, telemetry history, and agent-flow admission for the shared model boxes

Nothing that must survive indefinitely should live only in Valkey. Values stored there must either be reconstructable from source/projection state or safe to expire after their TTL.

Conversation history and conversation memory are canonical durable state. They are not application-cache entries and must not be moved to the shared model pool. Cache loss may cause recomputation; it must not erase a conversation or change its source scope.

ELS Compass Deployment Topology

The development and demo deployments share only the physical model workers and their scheduling control plane:

Participant

Environment-local state

Shared model path

Development API

.84 OpenSearch and application Valkey

restricted local 6380 tunnel to .199:6381/2

Demo API on .16

demo OpenSearch and application Valkey on .199:6379

restricted local 6380 tunnel to .199:6381/2

Primary monitor on .199

local logs only

direct .199:6381/2

Standby monitor on .17

local logs only

restricted local 6380 tunnel to .199:6381/2

Model workers

Ollama on .16 (box-c) and .17 (box-e)

fenced telemetry and leases in the shared model pool

The shared pool uses namespace aibs-shared-models and key prefix aibs:shared:model-coordination. Development and demo application caches use different databases, namespaces, prefixes, and credentials. Neither application cache is an authorization source; enabled-source and RBAC checks still run against canonical state.

Each participant has a separately revocable ACL identity. Passwords are read from service-local files and are never embedded in URLs. The SSH tunnel account on .199 has no shell and each key is limited to forwarding 127.0.0.1:6381.

The two monitor candidates provide monitor-process and monitor-host failover. They do not make the single .199 Valkey host highly available. Loss of .199 still makes model placement fail closed until the model pool is restored or moved to an independently replicated Valkey service.

Why Valkey Is Needed

The global model scheduler needs operations that are both fast and atomic:

  • read current node residency and active lease state;

  • compare requested resident/KV budget against node capacity;

  • reserve a node for one model call;

  • attach a TTL so abandoned leases self-heal;

  • release the lease after the model call finishes.

Doing that in process memory is only safe for a single API process. Doing it in OpenSearch would be heavier, slower, and less natural for expiring locks. Valkey fits the coordination shape: atomic Lua scripts, server-side time, TTLs, and low latency.

The scheduler uses server-side TIME in the Valkey script so all API processes evaluate lease freshness against the same clock authority instead of their own machine clocks.

What Uses The Coordination Plane

The coordination port is shared by several runtime concerns:

  • Global model placement. The scheduler reserves a specific node for a model call and returns the selected node URL to the LLM adapter.

  • Model residency monitoring. Node monitors publish recent Ollama residency observations so stale or unknown nodes are not selected.

  • Node host telemetry. Optional lightweight agents on each AI box expose CPU, memory, GPU busy, raw VRAM, and raw GTT for the System Health page. The UI presents VRAM and GTT separately; a derived aggregate may be shown only as additional context. These samples are read-only operator telemetry and do not replace the scheduler’s configured capacity budget or fenced residency facts.

  • Agent-flow admission. Broad agentic workloads use shared queue/active-flow state when a shared coordination backend is configured.

  • Projection repair fallback. If projection-control writes fail, dirty-state fallback records can be shared across processes.

  • Best-effort caches. Cache users may treat Valkey failures as misses; safety users must fail closed.

These are coordination facts, not business facts.

Failure Semantics

Valkey-backed model placement is deliberately fail-closed. If the scheduler cannot prove that a node is fresh, has capacity, and has an atomic lease, it must not place work onto that node.

The memory coordination adapter remains useful for local development and tests, but it is process-local. The application must not run AIBS_MODEL_CLUSTER_ENABLED=true with AIBS_COORDINATION_BACKEND=memory, because that combination would advertise global capacity control while every API process still has a private view of the world.

For best-effort cache paths, a Valkey failure should degrade into a cache miss. For lease-protected paths, a Valkey failure should deny or queue work rather than overcommit the model cluster.

Enablement Gate

Before enabling the global scheduler in an environment:

  1. Configure a shared model-coordination Valkey endpoint reachable by every API worker and monitor.

  2. Set AIBS_MODEL_COORDINATION_BACKEND=valkey and configure the canonical AIBS_MODEL_COORDINATION_VALKEY_* settings.

  3. Configure the model cluster node ids, URLs, GPU-memory budgets, and worker weights. The environment variable remains AIBS_MODEL_CLUSTER_NODE_VRAM_GB for compatibility, but the measured value must cover all GPU memory the node can safely use for model residency. Configure AIBS_MODEL_CLUSTER_NODE_MAX_PARALLEL_REQUESTS from the serving process’s verified parallel runner capacity; do not infer it from memory alone.

  4. Run audit_model_capacity until it reports the scheduler as ready.

  5. Run prove_model_monitor_takeover --repeat 3 --handover-gate strict from the target topology. Correctness requires zero pre-kill owner loss and zero successful fenced writes from a deposed owner. The complete timing bound (poll interval + election TTL + standby retry + two poll timeouts) must fit inside the configured residency-staleness window.

  6. Optionally install scripts/aibs_node_telemetry_agent.py on each model node and configure AIBS_MODEL_CLUSTER_NODE_HOST_TELEMETRY_URLS for host-load charts.

  7. Enable AIBS_MODEL_CLUSTER_ENABLED=true only after the gates are green.

The operational runbook is in docs/maintainance_&_operations/model_capacity_audit.md.