07

The Production Data Plane

Make durable state authoritative, acceleration disposable, and every storage split earn its operational cost.

The enterprise problem and today’s slice

Enterprise problem: A user expects the email agent to honor “no meetings before 10:00” while arranging Alice’s architecture review, but a restart, stale cache, cross-tenant vector result, or lost background job can produce the wrong proposal and destroy trust.

Whole-course context: The incoming artifact is a controlled email workflow that separates request-scoped graph state from semantic, episodic, and procedural memory and governs who may write each type.

Today’s slice: We turn that workflow into a durable generated-application data plane: PostgreSQL owns truth, specialized stores serve bounded roles, and queues isolate background learning.

End-of-day evidence: A reviewer receives a store-ownership matrix, an Alice-request trace, a tenant-isolation probe, a restore result, a cache-invalidation check, and a measured vector-scaling rule.

Still unsolved: Release evaluation, rollout, telemetry, incident ownership, and governance evidence remain for the shipping slice.

Choose authority before specialization

Vector infrastructure looks like the central choice, but the real risk is losing transactional authority; without one truth, dual writes can leave searchable vectors that no longer match permissions or deletion state. Rule: start with PostgreSQL plus pgvector, then split only the measured retrieval workload.

A simple profile preference fits one relational row and one vector. For Alice’s request, the repository first filters tenant_id, user_id, status = 'active', and embedding version, then ranks only that candidate set. Ranking first is a failure mode because a cross-tenant vector may enter the top-k before authorization. Decision rule: keep pgvector while it meets the labelled recall, filtered p95 latency, write rate, restore, and cost objectives; add Qdrant only when independent sharding, replication, or tuning closes a measured gap.

OptionUse whenAvoid whenMain trade-off
PostgreSQL + pgvectorMetadata joins, transactions, and one recovery path dominateVector load measurably harms transactional objectivesSimpler correctness; shared resource tuning
Qdrant or managed vector storeVector retrieval needs independent scale or operationsThe team cannot operate consistency, re-indexing, and deletion across two systemsSpecialized retrieval; second distributed system
OpenSearchLexical BM25, filters, aggregations, and vectors are all first-classYou need canonical transactional memoryStrong discovery; operational weight
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE memories (
  tenant_id uuid NOT NULL,
  user_id uuid NOT NULL,
  memory_id uuid PRIMARY KEY,
  content text NOT NULL,
  embedding vector(1536),
  embedding_model text NOT NULL,
  status text NOT NULL DEFAULT 'active',
  source_ref text NOT NULL,
  metadata jsonb NOT NULL DEFAULT '{}'
);

CREATE INDEX memories_hnsw
ON memories USING hnsw (embedding vector_cosine_ops);

Accelerate and decouple without moving authority

Fast components are often mistaken for durable ones, so eviction or queue delay can silently become data loss. Rule: Redis or Valkey caches computation, a queue carries retryable work, and object storage holds large content; none replaces PostgreSQL’s business truth.

A simple cache stores a hot profile for two minutes. In Alice’s request, the retrieval key includes tenant, user, query, memory epoch, embedding model, and policy version; superseding “after 10:00” with “after 12:00” advances the epoch. Omitting that epoch is the failure mode: a valid but stale hit schedules too early. Decision rule: cache only when a miss can safely reconstruct the value, and never replay cached send, schedule, or delete authority without fresh authorization.

Use a managed queue first for extraction, embedding, consolidation, and re-indexing; choose Kafka only when sustained throughput, ordered partitions, long replay, and multiple independent consumers justify it. Store raw MIME, attachments, large evaluation artifacts, and redacted snapshots in object storage with checksums, scoped identities, encryption, retention, and lifecycle deletion.

Version, degrade, and prove recovery

An apparently healthy service can return corrupted rankings or invent context during an outage, so migrations and degraded modes must be explicit before production traffic. Rule: every vector carries provider, model, dimension, normalization, content hash, and version; every dependency has a bounded fallback.

A simple migration builds a parallel index and changes one read-version pointer after evaluation. For Alice’s request, both versions must retrieve the active 10:00 preference inside the tenant boundary before cutover. Re-embedding in place is the failure mode because incompatible vectors mix silently and rollback disappears. Decision rule: switch only after labelled quality, latency, filtering, deletion, and rollback checks pass; retire the old index after the rollback window.

If semantic retrieval times out, a low-risk draft may continue using current-thread context while declaring durable preferences unavailable. A high-impact schedule action must stop because its safety depends on memory. If Redis fails, fall back to rate-protected PostgreSQL; if the queue fails, retain the outbox event. The operator’s final action is to run four probes: cross-tenant retrieval returns zero, replay produces one outcome, cache epoch change exposes the new preference, and a restore reconstructs the active memory plus its audit chain.

Key takeaways

A production data plane is safe when truth, acceleration, and asynchronous delivery have different owners and different failure behavior.

  • Keep PostgreSQL authoritative for checkpoints, memory records, idempotency, outbox events, and version pointers.
  • Filter by authenticated tenant and lifecycle state before vector ranking; a similarity score never grants authority.
  • Treat Redis or Valkey, queues, object storage, and dedicated vector indexes as bounded specialists, not interchangeable databases.
  • Add Qdrant or another vector service only after labelled quality, latency, recovery, and operating-cost evidence justifies the split.
  • Version embeddings, preserve rollback, define degraded modes, and prove restoration before trusting the architecture.

Checklist

A production data plane is ready for the next slice only when its safety claims are executable rather than architectural promises.

  • [ ] Trace Alice’s request from authenticated identity to one committed 14:00 proposal.
  • [ ] Prove a cross-tenant retrieval returns zero and leaves the positive control intact.
  • [ ] Retry a pending outbox event and observe one terminal memory-policy decision.
  • [ ] Advance a memory epoch and prove the stale cache cannot win.
  • [ ] Benchmark a parallel embedding index, reject a failing cutover, and restore PostgreSQL from backup.