hyphae-server process that owns the in-memory
HNSW mesh, talking to an external PostgreSQL instance that is the system of record. This page covers
how to run that process — its two run modes, the volumes it needs, the Kubernetes wiring, and the
production hardening posture.
For a local stack, start with /operations/docker-compose. For the
reasoning behind this shape, see /operations/deployment-operations.
Run modes
The same binary runs in two modes:
Daemon mode is the deployable service. MCP stdio mode is for launching the server as a tool process
(for example, from Claude Code) and binds no network ports.
Boot sequence
On start, the daemon connects to PostgreSQL, runs migrations and verifies the dimension/model contract, builds the embedder, ensures a bootstrap admin exists, rehydrates the mesh from storage, and begins serving with graceful signal handling:Persistent volumes
A production deployment needs three durable volumes:Embedding packaging
The embedding model is large and changes less often than the binary, so it does not belong in the app image. Choose one of three delivery modes through configuration:1
Init-container warm (recommended)
A small init container pre-downloads the weights into the shared
model-cache volume mounted at
the embedding cache path. The app image stays small and the server starts with a warm cache.2
Baked Candle
Weights are copied into a custom image and the provider is
candle (the engine itself is
compiled into the default image — only the weights need baking). Use this for air-gapped or
immutable single-artifact deploys where the larger pull is acceptable.3
TEI sidecar
Set
HYPHAEDB_EMBEDDING_PROVIDER=tei and run a co-located TEI container. The weights live in the
sidecar, keeping both the app image and the volume free of model files.Kubernetes probes
Wire liveness and readiness so Kubernetes cooperates with mesh rehydration rather than fighting it:livenessProbe→GET /healthz. Gates on nothing external and stays200throughout rehydration, so Kubernetes never kills a pod that is correctly rebuilding its mesh.readinessProbe→GET /readyz. Returns ready only once every probe (storage, embedding, audit, graph) isUp, so the load balancer never routes to an instance still loading its mesh. The gRPC alternative (readinessProbe.grpcon port 50051) probes the same evaluator via the standardgrpc.health.v1service, which starts fail-closedNOT_SERVING; prefer the HTTP form — its response body names the failing probe.
deploy/k8s/ and Helm manifests use.
For high availability, run two replicas with HYPHAEDB_HA_ENABLED=1 (the Helm chart wires the
env automatically at replicaCount > 1, where the PodDisruptionBudget also activates): the
lease-race loser runs as a zero-write standby (/readyz 503, so no traffic routes to it) and
promotes automatically when the primary dies or drains. Never run two instances without the
flag — they would both act as primary against the same PostgreSQL. See
/operations/high-availability.
Production posture
The service introduces a deployment profile that gates security:- Dev permits plaintext binds on loopback for friction-free local work.
- Production mandates TLS/mTLS on every listener (a listener refuses to start without a TLS identity), secrets resolved through a manager rather than raw env, and encryption at rest on sensitive columns.
Operational artifacts
The repository ships these underdeploy/: