# Frequently asked questions (FAQ)

> **CocoIndex v1, Rust SDK (experimental).** This page documents the CocoIndex **v1** Rust SDK (the `cocoindex` crate). The Rust SDK is experimental: any release may change or remove its API, and it is not yet published on crates.io. The Python SDK pages are at https://cocoindex.io/docs/.
>
> Source: https://cocoindex.io/docs/rust/faq/ · Rust docs index: https://cocoindex.io/docs/rust/llms.txt · Rust SDK tour: https://github.com/cocoindex-io/cocoindex/blob/main/rust/sdk/SHOWCASE.md · Rust examples: https://github.com/cocoindex-io/cocoindex/tree/main/examples/rust

## Change detection

### Why do logic changes propagate transitively but input changes don't?

In the call chain `foo(a)` → `bar(b)`:

- **Logic changes propagate**: if `bar`'s logic changes (code, `deps`, `version`), the output of `foo(a)` could be different too, so `foo`'s memo must be invalidated.
- **Input changes don't propagate**: `b` is the result of applying part of `foo`'s logic to `a`. As long as `foo`'s logic and `a` are unchanged, `b` won't change — there's nothing to propagate.

### How does logic change propagation work?

Logic changes propagate based on **runtime invocations**, not static call graphs. Two consequences:

- **Unannotated functions don't break the chain.** If `f1()` → `f2()` → `f3()`, and `f1` and `f3` are decorated with `@coco.fn` but `f2` is not, a logic change in `f3` still invalidates `f1`'s memo.
- **Conditional calls are tracked precisely.** If `f1()` calls `f2()` only in one branch, then invocations of `f1()` that didn't call `f2()` are not invalidated when `f2`'s logic changes — only invocations that actually called `f2()` are affected.

### What about hidden dependencies like global variables or files?

Like any memoization system (e.g., `@functools.cache`), CocoIndex's change detection assumes functions depend only on their declared inputs. If a function reads a global variable, a file, or external state not passed through arguments, CocoIndex won't detect changes to those automatically.

CocoIndex provides mechanisms to capture some of these dependencies:

- **[`deps`](/docs/rust/programming_guide/function/#deps)** — declares module-level values (like a prompt string or model name) as part of the function's logic. Changes to these values invalidate dependent memos, just like any other logic change. Note: `deps` is snapshotted once at decoration time.
- **[`use_context()`](/docs/rust/programming_guide/context/)** — retrieves shared resources via `ContextKey`. With [`detect_change=True`](/docs/rust/programming_guide/context/#change-detection), changes to the provided value invalidate dependent memos.

For per-call values that change at runtime, pass them as regular function arguments instead.

## Target states and syncing

### What happens if my pipeline crashes mid-update?

CocoIndex's internal state stays consistent after a crash or `kill -9`. On the next `app.update()`, CocoIndex automatically recovers: it computes the current desired state and reconciles against all possible previous states, converging the target to the correct state. No manual cleanup is needed. See [Error Handling — Interrupted updates and recovery](/docs/rust/advanced_topics/exception_handlers/#interrupted-updates-and-recovery) for details.

### Are target state writes transactional across targets?

Not across targets. When a processing component finishes, CocoIndex sends all its target state changes to each target backend as a unit. All writes happen after processing completes, never partially during execution. Each target backend applies its batch atomically when supported (e.g., within a database transaction). A batch may also carry the changes of several components that finish around the same time; if the backend rejects it, CocoIndex retries the changes in smaller batches per component, so one component's failure never undoes another's. But changes across *different* target backends (e.g., Postgres and local files) are not transactional with each other. See [How target states sync](/docs/rust/programming_guide/processing_component/#how-target-states-sync) for details.
