Same diagram as Mermaid
Same diagram as Mermaid
Same system as a UML deployment diagram
Same system as a UML deployment diagram
Nodes are execution environments and artifacts are what runs on them, so this view
answers “what is deployed where” rather than “what happens next”.PlantUML source, so the next editor regenerates rather than redraws:
The boundary, first
BYOC splits on one line: you provide the substrate, Mixpeek provides and operates the software. The eight stages below each answer the same four questions: input, work, output, resources.Stage by stage
① Arrival
Sync providers today:
google_drive, s3, snowflake, sharepoint, tigris, iconik.
Modes are initial_only or continuous with a polling_interval_seconds. Continuous
sync is polling, not an event subscription, which sets your latency expectation for “a
video arrives”.
② Object
A video is one object with blobs, not many objects. Decomposition into chunks, frames
and scenes happens in stage ⑤, which is what makes tiers necessary.
③ Batch
dedup_strategy is the cost-multiplying knob: a re-run with the wrong value re-pays full
extraction. Tier 0 is bucket to collection; tier N above 0 is collection to collection.
A pipeline that turns a video into chunks, chunks into frames, and frames into embeddings is
three tiers, each independently tracked and retryable.
④ Schedule
This is where the extractor stops being a name and becomes a machine.
Profile resolution is a six-rule ladder:
Only 6 of 12 built-in extractors declare a profile. For the rest,
requires_gpu decides
the hardware, not anything named in the definition. Choosing an extractor chooses a node
pool and therefore a bill.
Sizing is object_count ÷ objects_per_worker → replicas, clamped by the tenancy slice and a
350Gi ceiling. Shared tenancy gets gpu 2 / cpu 32 / api 4; DEDICATED_GPU rises to gpu 8 /
api 12.
⑤ Execute
Two Ray shapes, and confusing them is the usual mistake. The RayService is long-lived
and holds the models. The RayJob is ephemeral, one per batch, and holds no models at all for
Serve-backed extractors. A
cpu-only worker’s real peak is about 0.27 core and 0.77 GiB,
which is why its requests are 1 cpu / 2Gi and why one node holds seven or eight concurrent
batches instead of three.
Two mechanics worth carrying:
- Kubernetes
cpu_reqis not Raynum-cpus.cpu_workers.ray_num_cpusdecouples them, so a worker can advertise 2 schedulable CPU to Ray for placement groups while requesting 1 from Kubernetes. Without it, multi-step streaming placement cannot schedule and the job orphans. - Requests drive the autoscaler; limits are the OOM gate. Limits stay generous so a decode or frame burst is absorbed rather than OOMKilled.
⑥ Persist
The knobs that decide cost and recall:
Durability, stated plainly: the recovery source is object storage. A rescheduled primary
replays the sealed WAL plus snapshot, so RPO is bounded by the flush interval rather than by
zero. Replicas serve reads and do not shorten that gap.
Replica counts vary by namespace, and a namespace under maintenance can run a shape that
does not match the steady state above. Treat this section as the design, and read the
actual pod counts in your own namespace before depending on them.
⑦ Enrich and classify
Flat taxonomy enrichment calls no language model. It matches against a reference collection
and writes labels back. Hierarchy inference has three methods, and only the LLM-based one
calls a provider.
Taxonomy is a small part of the egress picture, and the section below is the whole of it.
⑧ Decide
This stage composes primitives; there is no moderation resource in the API.What leaves your account
Egress is not a property of one stage. It is a property of which extractors and which retriever stages a pipeline is configured with, and it exists at both ingest and query time. Enumerated from the call sites rather than characterised, because every attempt to describe this as a category has been wrong: At ingest, a model-backed extractor sends the content itself.gemini_multifile_extractor
builds Gemini parts with Part.from_bytes(data=content, mime_type=...), so for an image or a
PDF the media goes to the provider, not a label derived from it. The same holds for
multimodal_extractor v2 Gemini embedding, universal_extractor, scrolling_text_extractor,
document_graph_extractor’s VLM corrector, and web_scraper’s semantic router. Cluster
labelling calls a model too.
At query time, seven retriever stages call providers: enrich/llm, enrich/agentic,
filter/llm, filter/agent_search, filter/attribute, filter/query_expand and
reduce/summarize. The enrich family is the volume path, once per result, so an enrich
stage over 100 results is 100 calls.
Those same seven also run at ingest, whenever a taxonomy or a collection’s
retriever_enrichments points at a retriever. That path fires once per document rather
than once per result, which makes it the larger volume of the two on a bulk load. Reading
the collection will not tell you, because its config carries only a retriever_id; you
have to follow the reference to the retriever and read its stages.
Which of these are in your pipeline is configuration. A pipeline built on self-hosted
models in your own Serve deployments makes none of these calls. One built on
gemini_multifile_extractor sends every object’s bytes to Google at ingest. Both are
supported, and the difference is a choice you make per collection and per retriever rather
than a property of the platform.
Three things change the answer, and all three are available today:
- Your own provider credentials. Organization-default LLM credentials resolve per request, so these calls can run on your OpenAI, Anthropic or Vertex account. The egress becomes your contract with the provider rather than ours.
- Self-hosted models. Anything served from your own Ray Serve deployments stays inside your VPC end to end.
- Replace the path. A custom plugin can take over the enrich batch entirely, so the built-in provider call is never made.
Model weights are a different kind of egress
No customer content leaves on a self-hosted-model pipeline, which is the commitment above. The weights do arrive from outside, carrying nothing of yours, from HuggingFace and similar hosts. Two of the six model sets are baked into the engine image and need no network at all. The other four are fetched the first time each replica loads them, not at image build:
It matters operationally rather than for a privacy review, and the failure is easy
to misread. A namespace with no outbound to the public internet brings the Ray
cluster up healthy and then leaves those four applications unable to load, which
reads as a slow install for as long as it takes someone to look at the Serve status.
Decide it before the first deploy. Either allow egress to
huggingface.co on first
start, or ask us for an image with all six baked.
Query path
Retrieval reuses the index the ingest path built.
Read mechanics: coordinator →
SearchDense RPC (fan-out across the hash ring for
multi-shard namespaces) → shard probes nprobe partitions via PQ codes → re-ranks top-N
against raw vectors → returns point id, score and payload.
Filter predicates are evaluated coordinator-side, after the shard returns. That is known
waste, and it is what compute pushdown is for.
Resource map
Where it breaks
Back-pressure and failure points, in the order they bite:
One correctness note, because it is invisible otherwise: a batch that finishes with a failed
tier reports
COMPLETED_WITH_ERRORS, not COMPLETED. If you build a gate that polls batch
status, poll for the honest values.
What this page does not establish
- Where the control plane sits. The section above states the disagreement rather than picking a side. The install kit deploys no API, so it is the permission grant rather than the workload and does not settle it either.
- A live BYOC deployment. Stage-by-stage resource numbers are read from the shared production cluster, which is the same software on Mixpeek’s substrate. Your pools, quotas and storage classes are yours and will differ.
- Networking and egress detail. VPC layout, private-link options and per-provider network paths are untraced. What is enumerated is the set of call sites that reach a model provider, listed above. That list was wrong three times before it was right, each time by describing the category instead of counting: treat it as accurate on its date and derive the live set from a namespace’s own configured extractors and stages.
- Moderation as a product surface. It does not exist as a resource. Stage ⑧ is a composition, and the destination-write gap is real.
- Continuous sync latency. Sync polls on
polling_interval_seconds. End-to-end arrival latency is unmeasured for every provider.
Deployment models
The shapes Mixpeek runs in, and which planes sit where.
Single tenant
Dedicated tenancy, and what changes about the numbers above.

