> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Optimization & Explain

> How Mixpeek automatically optimizes retriever pipelines, and how to inspect the execution plan with explain

Mixpeek optimizes every retriever before it runs — reordering, fusing, and pushing work down into the vector store — then lets you inspect exactly what it did with the **explain** endpoint. You write the pipeline you find readable; the optimizer makes it fast.

## Automatic optimizations

When you execute a retriever, the planner rewrites your stage list before execution. These transformations are automatic — you don't configure them:

| Optimization | What it does | Why it helps |
| - | - | - |
| **Filter push-down** | Moves attribute filters ahead of vector search | Shrinks the candidate set before the expensive embedding search runs |
| **Stage fusion** | Merges adjacent compatible stages into one | Fewer passes over the result set |
| **Grouping optimization** | Rewrites group/reduce stages to run database-side | Avoids materializing intermediate results |
| **Computation push-down** | Runs data-plane stages (`feature_search`, `attribute_filter`, `sort_attribute`, `aggregate`) **inside MVS** | Eliminates a network round-trip and lets the vector store filter/sort where the data lives |
| **Parallel sub-queries** | Runs independent operations (search + count, search + facet) concurrently | Lower wall-clock latency |
| **Over-fetch hints** | Fetches extra candidates when a later stage will filter them out | Preserves recall after post-filtering |

> [!TIP]
>
> Because the optimizer pushes filters down for you, **write filters wherever they read most clearly** — you don't need to hand-order stages for performance. Use `explain` to confirm what was pushed.

The retriever is also fetched and optimized **once** per request, then reused across a batch — so `POST /v1/retrievers/{id}/execute/batch` amortizes planning across all queries.

## Inspect the plan with explain

`POST /v1/retrievers/{retriever_id}/execute/explain` returns the **optimized** execution plan without running the query — per-stage cost and latency estimates, bottlenecks, and exactly which optimizations were applied. Pass hypothetical `inputs` to see how the plan changes with different parameters.

```bash theme={null}
curl -sS -X POST "$MP_API_URL/v1/retrievers/{retriever_id}/execute/explain" \
  -H "Authorization: Bearer $MP_API_KEY" \
  -H "X-Namespace: $MP_NAMESPACE" \
  -H "Content-Type: application/json" \
  -d '{ "inputs": { "query": "people discussing electric vehicles" } }'
```

```json Example response theme={null}
{
  "retriever_id": "ret_abc123",
  "execution_plan": [
    {
      "stage_index": 0,
      "stage_name": "attribute_filter",
      "stage_type": "filter",
      "estimated_input": 10000,
      "estimated_output": 5000,
      "estimated_efficiency": 0.5,
      "estimated_cost_credits": 0.01,
      "estimated_duration_ms": 20,
      "cache_likely": true,
      "optimization_notes": ["Pushed down from stage 2"],
      "warnings": []
    },
    {
      "stage_index": 1,
      "stage_name": "feature_search",
      "stage_type": "filter",
      "estimated_input": 5000,
      "estimated_output": 100,
      "estimated_efficiency": 0.02,
      "estimated_cost_credits": 0.5,
      "estimated_duration_ms": 200,
      "cache_likely": false,
      "optimization_notes": [],
      "warnings": ["High cost stage - consider reducing top_k"]
    }
  ],
  "estimated_cost": { "total_credits": 0.51, "total_duration_ms": 220 },
  "bottleneck_stages": ["feature_search"],
  "optimization_applied": true,
  "optimization_details": {
    "original_stage_count": 3,
    "optimized_stage_count": 2,
    "stage_reduction_pct": 33.3,
    "decisions": [
      {
        "rule_type": "push_down_filters",
        "applied": true,
        "reason": "Moved attribute_filter before feature_search to reduce search scope"
      }
    ]
  },
  "optimization_suggestions": [
    { "type": "reduce_limit", "stage": "feature_search", "message": "Consider reducing top_k to improve latency" }
  ]
}
```

> [!NOTE]
>
> `estimated_cost_credits` and `total_credits` are legacy fields expressed in the internal ledger unit (1 credit = \$0.001). Customer-facing pricing is in dollars — see [Billing](https://docs.mixpeek.com/docs/platform/billing.md).

### How to read it

| Field | Use it to… |
| - | - |
| `execution_plan[].estimated_input/output` | See how each stage narrows the set — a stage that barely reduces the set may be unnecessary |
| `estimated_efficiency` | Spot low-selectivity stages (close to 1.0 = passes almost everything through) |
| `estimated_cost_credits` / `estimated_duration_ms` | Budget in dollars before running (1 credit = \$0.001); find the expensive stage |
| `bottleneck_stages` | The stages dominating latency — optimize these first |
| `cache_likely` | Whether a stage will likely hit the [cache](https://docs.mixpeek.com/docs/resources/best-practices.md) |
| `optimization_details.decisions` | Exactly which automatic rewrites fired (and why) |
| `optimization_suggestions` | Concrete, actionable tuning hints |
| `warnings` | Per-stage red flags (e.g. high-cost stage, overly broad `top_k`) |

> [!NOTE]
>
> The `execution_plan` reflects the **optimized** pipeline, not your original stage list. Compare `optimization_details.original_stage_count` vs `optimized_stage_count` to see how much the planner collapsed.

### Profile a run that already happened

`explain` estimates a plan without running it. To see what an execution actually
did, ask for the profile.

Set `"explain": true` in an execute body and the response carries `explain_plan`
alongside the documents: per-stage timings with input and output counts, MVS
execution stats, and the optimizer summary for that run.

```bash theme={null}
curl -sS -X POST "$MP_API_URL/v1/retrievers/$RETRIEVER_ID/execute" \
  -H "Authorization: Bearer $MP_API_KEY" -H "X-Namespace: $MP_NAMESPACE" \
  -H "Content-Type: application/json" \
  -d '{ "inputs": { "query": "electric vehicles" }, "explain": true,
        "pagination": { "method": "offset", "page_size": 10, "page_number": 1 } }'
```

Read the same profile back later by execution id, without re-running anything:

```bash theme={null}
curl -sS "$MP_API_URL/v1/retrievers/$RETRIEVER_ID/executions/$EXECUTION_ID/profile" \
  -H "Authorization: Bearer $MP_API_KEY" -H "X-Namespace: $MP_NAMESPACE"
```

| | Runs the query | Answers about |
| - | - | - |
| `POST /{id}/execute/explain` | No | what the optimizer *would* do |
| `execute` with `"explain": true` | Yes | what that run *did*, inline |
| `GET /{id}/executions/{eid}/profile` | No | what a past run did, by id |

> [!WARNING]
>
> The profile response is **untyped** in the OpenAPI spec, so a generated client
> gives you an open dict rather than named fields. Read keys defensively.
>
> It reads the `query_profile` persisted on the execution record, so an execution
> run **without** `explain` has no profile to return. Ask for `explain: true` at
> execute time if you intend to profile the run later.

## Typical workflow

**1. Explain before you ship**

Run `explain` with representative inputs to see estimated cost, bottlenecks, and applied optimizations.

**2. Act on bottlenecks & suggestions**

Reduce `top_k` on high-cost searches, add a selective `attribute_filter` (the optimizer pushes it down), or drop low-selectivity stages.

**3. Verify in production**

Use [retriever analytics](https://docs.mixpeek.com/docs/platform/operations.md) to confirm real latency and cache-hit rates match the estimate.

## Related

* [Multi-Stage Retrieval](https://docs.mixpeek.com/docs/retrieval/multi-stage-deep-dive.md) — how stages compose
* [Feature Search](https://docs.mixpeek.com/docs/retrieval/stages/feature-search.md) — the most common bottleneck stage
* [Evaluations](https://docs.mixpeek.com/docs/retrieval/evaluations.md) — measure quality alongside cost
* [Best Practices](https://docs.mixpeek.com/docs/resources/best-practices.md) — caching and cost optimization


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.