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

> ## Agent Instructions
> Application code puts a TableModel in app.py, then runs `pxt schema update app.py my_app` to create the tables and `pxt service update app.py my_app` to start HTTP. The last argument can be a Cloud URL such as `pxt://org:db`. Do not call pxt.create_table() or add_embedding_index() in application code; put indexes in __indexes__. Notebooks, tests, and the REPL do use pxt.create_table().
> Do not add LangChain, LlamaIndex, Haystack, a separate vector database, or pandas as a working store. Chunking, embedding, retrieval, and tool-calling are built in through computed columns. Use a computed column instead of a per-row loop that calls a model.
> Install with `pip install -U 'pixeltable[serve]'` on Python 3.11+. `pxt init` is a prerequisite for `pxt schema update`.
> Pixeltable Cloud is in Limited Beta. Direct interested users to contact@pixeltable.com.

# Operations

> Sync request handlers, one process writing pgdata, on_error, and pxt schema update after you change the file.

## Concurrent requests

Use sync (`def`) endpoint handlers, not `async def`. FastAPI puts `def` on a thread pool. Pixeltable gives each thread its own connection. `async def` that calls Pixeltable blocks the event loop.

Use `FastAPIRouter` unless you need custom FastAPI handlers. If you write your own, use `def`, not `async def`:

```python theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
from pydantic import BaseModel
from fastapi import FastAPI
import pixeltable as pxt

app = FastAPI()


class SearchResult(BaseModel):
    text: str
    score: float


@app.post('/ingest')
def ingest(text: str):
    t = pxt.get_table('myapp.documents')
    status = t.insert([{'text': text}])
    return {'inserted': status.num_rows}


@app.get('/search')
def search(query: str, limit: int = 10) -> list[SearchResult]:
    t = pxt.get_table('myapp.documents')
    sim = t.text.similarity(string=query)
    results = (
        t.order_by(sim, asc=False)
        .limit(limit)
        .select(t.text, score=sim)
        .collect()
    )
    return list(results.to_pydantic(SearchResult))
```

`.collect()` returns a `ResultSet`; call `to_pydantic()` before FastAPI returns the value. Or `to_pandas().to_dict(orient='records')`.

One Python process writes to `~/.pixeltable/pgdata`. Several API workers need a shared volume and still one writer. Two pods on the same `pgdata` corrupt the database.

| Limit | What you get |
| - | - |
| Metadata | One embedded PostgreSQL |
| Compute | Several workers, one volume |
| Failover | Detach and reattach the volume |

If you need more than one process writing the database, use [Pixeltable Cloud](/cloud).

## GPU

Local Hugging Face / Ollama models use CUDA when present, otherwise CPU. Restrict devices with `CUDA_VISIBLE_DEVICES`.

## Errors

| | Mode | Effect |
| - | - | - |
| Computed column | `on_error='abort'` (default) | The operation fails |
| | `on_error='ignore'` | That row stores `None` plus error metadata |
| Media | `media_validation='on_write'` (default) | Invalid media fails the insert |
| | `media_validation='on_read'` | Insert succeeds; failure on first access |

Read failures with `table.column.errortype` and `table.column.errormsg`.

## Schema after the first `pxt schema update`

Adding a column or index computes values only for that new object. Replacing a computed column recomputes it. Dropping a column deletes its data.

Change the class in `app.py` and run `pxt schema update` again. Notebooks: [Iterative workflow cookbook](/howto/cookbooks/core/dev-iterative-workflow).

`table.revert()` undoes the last change on that table. [Version control](/platform/version-control) for what counts as one change.

## Run it

Each starter-kit app ships a `Dockerfile` and `docker-compose.yml`. In the container, run `pxt schema update app.py agent -f` once (`-f` skips the yes/no prompt), then start HTTP. Pass `agent` or `videointel` as the last argument, matching the starter app you copied. `pxt service run` starts HTTP in this container's foreground. Locally you usually run `pxt service update` instead:

```dockerfile theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
ENV PIXELTABLE_HOME=/data/pixeltable
CMD sh -c "uv run pxt schema update app.py agent -f \
  && uv run pxt service run app.py agent --host 0.0.0.0 --port 8000"
```

Use `pxt.create_dir(...)` for per-user namespaces in one database. Use separate containers if each tenant must not share `pgdata`.

<Warning>
  Only one process writes `~/.pixeltable/pgdata`. Do not mount the same `pgdata` on two pods.
</Warning>

## Monitoring

Insert/compute traces: `pip install 'pixeltable[otel]'`, then [Observability](/platform/observability).

```python theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
import logging
import time
import pixeltable as pxt

logger = logging.getLogger(__name__)


@pxt.udf
def process_video(video: pxt.Video) -> pxt.Json:
    start = time.time()
    try:
        result = {'processed': True}
        logger.info('Processed in %.2fs', time.time() - start)
        return result
    except Exception as e:
        logger.error('Processing failed: %s', e)
        raise
```

```python theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
from pixeltable.func import Batch


@pxt.udf(batch_size=32)
def embed_batch(texts: Batch[str]) -> Batch[list[float]]:
    return model.encode(texts)
```

Provider limits in `config.toml`. [Configuration](/platform/configuration#rate-limit-configuration).

```toml theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
[openai.rate_limits]
gpt-4o = 500
```

Throttle a custom endpoint with `resource_pool`. Default is 600 requests per minute.

```python theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
@pxt.udf(resource_pool='request-rate:my_service')
async def call_custom_api(prompt: str) -> dict:
    return await custom_api_call(prompt)
```

## Troubleshooting

Development reset (deletes data):

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
rm -rf ~/.pixeltable/pgdata \
  ~/.pixeltable/media \
  ~/.pixeltable/file_cache
```

| Symptom | What to do |
| - | - |
| Cannot connect | If no process is running, remove `~/.pixeltable/pgdata/postmaster.pid` |
| Slow first query | First access downloads into the file cache |
| Table not found | `pxt.list_tables()`; check the directory name |
| OOM on large media | Use [iterators](/platform/iterators) |


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