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

# The fitted context

> Reuse one fit across many predictions

```python theme={null}
clf = Hollerith()
clf.fit(train, target="churned")   # the training table is uploaded once

clf.predict(batch_1)               # sends batch_1 only
clf.predict(batch_2)               # sends batch_2 only
```

The fitted context is the one piece of state Hollerith keeps for you. Everything else in the
SDK is stateless.

## What fit gives you back

`fit` leaves an artifact on our side and binds your client to it. Two attributes describe it.

```python theme={null}
clf.fitted_context_id_          # 'k5741bd3c9x2m8p0rq6vtn3z9h'
clf.fitted_context_expires_at_  # '2026-08-14T09:12:44.000Z'
```

The id is a raw document id, with no prefix in front of it. Store it as an opaque string.

Each `fit` creates a new context with a new id. Fitting twice does not replace the first
context, it leaves two, and there is no endpoint to delete either one.

## A context lives 7 days, it is gone

A context lives 7 days from the `fit` that created it. Predicting against it does not extend
the clock, and there is no way to renew it.

After expiry, a predict raises `NotFoundError` with code `fitted_context_expired`, or
`fitted_context_not_found` if the id was never yours. The fix in both cases is to call `fit`
again and keep the new id.

## Resuming in another process

```python theme={null}
clf = Hollerith.from_fitted_context("k5741bd3c9x2m8p0rq6vtn3z9h")
preds = clf.predict(batch_3)
```

The client fetches the context's schema — feature names, target, task — and binds to it. No
training rows are sent, because this process never had them.

Two things a resumed client cannot do:

* **`evaluate()` raises `RuntimeError`.** Evaluation needs the labeled table, and that only
  exists in the process that called `fit`.
* **`classes_` is unset until `predict_proba` runs.** The class list comes back from the
  engine on that call, not from the context schema.

## Three ways you lose the fast path

"predict never re-sends your training table" is true only while a context is bound. When one
is not bound, `predict` uploads the whole training frame with every call and bills it every
time.

Check `clf.fitted_context_id_` before you build a scoring loop on it. It is `None` in three
cases:

* **Before any fit.** A fresh client has no context, and `predict` raises `RuntimeError`. This
  is the one case that tells you.
* **With `server_context=False`.** Contexts are off for the whole client. Every `predict`
  ships the training table inline, with no warning.
* **After `fit(wait=False)`.** The call returns a `FitHandle` before the context is ready, so
  nothing ever binds — not even once the fit succeeds.

```python theme={null}
handle = clf.fit(train, target="churned", wait=False)
handle.wait()                                     # block until the context is ready
clf = Hollerith.from_fitted_context(handle.id)    # bind it explicitly
```

<img className="block dark:hidden" src="https://mintcdn.com/monarcha-53b27419/8XBoJyUBLB_e0wrZ/images/fitted-context-light.svg?fit=max&auto=format&n=8XBoJyUBLB_e0wrZ&q=85&s=8db3a8b9395013c27269c035520ee528" alt="What crosses the wire on each call, with a fitted context bound and without one" width="700" height="284" data-path="images/fitted-context-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/monarcha-53b27419/8XBoJyUBLB_e0wrZ/images/fitted-context-dark.svg?fit=max&auto=format&n=8XBoJyUBLB_e0wrZ&q=85&s=f3dee192048fadaba3ffded6b675a5fb" alt="What crosses the wire on each call, with a fitted context bound and without one" width="700" height="284" data-path="images/fitted-context-dark.svg" />

## What it costs

A context-backed predict bills the rows you score twice — once as input, once as output. For
`testRows` scored, that is `2 × testRows`.

An inline predict bills `trainRows + 2 × testRows`, so the context is cheaper by exactly your
training table on every call. Full accounting is in
[Usage and billing](/account/usage-and-billing).

## What is kept

The rows you upload are purged when the job reaches a terminal state — on failure as well as
on success. That covers both training rows and rows to score.

The context artifact is a separate thing, derived from your training table, and it persists
until the 7-day expiry. The context's row, including your feature column names, is retained
after that.

More in [Data handling](/account/data-handling).

## Next

* [How Hollerith works](/concepts/how-hollerith-works) — why there is a context at all
* [Errors](/reference/errors) — the not\_found codes in full
* [Limits](/reference/limits) — 200,000 rows per predict, 7-day TTL
* [Usage and billing](/account/usage-and-billing) — what each job kind bills
