# Residency

> USearch for Python

Where the payload lives and which engine traverses it is the constructor you call rather than a keyword you pass, one per C lifecycle verb and residency:

```python
DenseIndex.init_ram(256, memory_domains=[0, 1])  # Empty, one shard per NUMA node
DenseIndex.init_vram(256, devices=[0, 1])  # Empty, one shard per CUDA ordinal
DenseIndex.load_vram("index.safegraphs", devices=[0, 1])  # Uploaded from a checkpoint
DenseIndex.view_nvme("index.safegraphs.json", paths=["/mnt/nvme0"])  # Served in place from disk
```

`dimensions`, `metric` and `quantization` stay positional in both empty constructors, and everything after them is keyword-only: `connectivity`, `values_per_key`, and the one residency arm that constructor accepts.
Handing a constructor another residency's arm, such as `devices` to `init_ram`, raises a `TypeError` rather than being quietly ignored.

Shards are never replicated, so eight devices host eight slices of one graph rather than eight copies, and an index outgrowing them fails rather than paging to the host, so the answer is to name more devices.
An NVMe path is whatever identifies a device to an engine that can reach it: a filesystem path names a kernel device, a transport identifier selects a userspace engine, and a FUSE mount is how object storage stages in without an HTTP stack.
External-memory graphs are never modified in place, so an NVMe handle is a view and every mutating verb fails on it; bigger ones come from [absorbing](https://www.unum.cloud/docs/usearch/python/refinement.md#absorbing--splitting).

`import usearch`

## Residency

Where a handle's payload lives.

```python
class Residency(IntEnum)
```

- `RAM` = `1`: Host memory, traversed by CPU threads.
- `VRAM` = `2`: Accelerator memory, traversed by GPU warps on chosen devices.
- `NVME` = `3`: Persisted on drives, traversed through I/O engines and sized past RAM.

