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

# VPoints

> A VPoint (variation point) is a named, interceptable seam around a function — registered once, safe in production, and controllable from tests.

A **VPoint** (variation point) is a named seam around a function or method. You register it once at startup; every call then routes through the Varianz pipeline, where session-scoped [stages](/concepts/stages) can sample inputs and outputs or override the result.

The model is the same in every language: **register once, call many.** Get a runtime handle, register your VPoints against it, then call the returned or instrumented function per request.

```python theme={null}
@vz.vpoint(name="payment/charge")
def charge(request: ChargeRequest) -> ChargeResult:
    ...
```

Three properties make VPoints safe to adopt incrementally:

* **Pass-through by default.** With no stages attached (or with the SDK [disabled](/reference/configuration)), a VPoint runs the original function directly on a fast path. You can merge instrumentation before any registry exists.
* **You choose what to instrument.** Varianz doesn't require instrumenting all your code — annotate the functions that matter: payment charges, external calls, decision points you want to test around.
* **Session-scoped control.** Stages attach per test session; traffic without a session ID never sees them.

## Names

Every VPoint has a name. Give it explicitly, in `scope/entity` form:

```
payment/charge
pricing/calculate-price
email/send-confirmation
```

Names are kebab-case segments separated by `/`. The first segment is a logical grouping (often the owning domain or service area); the last is the operation. Under the hood, names canonicalize to a four-part form (`org/pkg/scope/entity`) with the missing parts derived from your code's package structure — tests can target a VPoint by any unambiguous suffix on `/` boundaries. See [Naming and routing](/reference/naming-and-routing) for the full rules.

<Tip>
  Always name VPoints explicitly. Auto-derived names come from package and class names, which makes them fragile under refactoring.
</Tip>

## Schemas

When a VPoint registers, the SDK derives a **schema** from the function's parameter and return types — field names, types, and nested structures. The schema is what makes stages safe: CEL expressions are validated against it before they run, so a typo'd field name or a wrong type is caught at insert time, not in the middle of a test.

Where the schema comes from differs by language:

| Language      | Schema source                                                                                                            |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Python        | Type annotations at decoration time; unannotated functions fall back to introspecting the first real call ("lazy")       |
| TypeScript    | The `@varianz/scanner` build step derives schemas from your TS types; `@struct`/`@field` decorators override when needed |
| Go            | Struct reflection with `json`/`protobuf`/`varianz` tag support; `varianz-gen` pre-computes schemas at build time         |
| Java / Kotlin | The annotation processor derives schemas from method signatures at compile time                                          |

Prefer the static path (annotations, scanner, codegen) — lazily-resolved VPoints don't exist in the registry until their first call, which means tests need a warmup request before stages can apply. See [Build integration](/guides/build-integration).

## VPoints in each language

The registration idiom follows each language's conventions — decorators in Python and TypeScript, a higher-order wrapper in Go, annotations in Java and Kotlin:

| Language   | Idiom                                                             | Reference                          |
| ---------- | ----------------------------------------------------------------- | ---------------------------------- |
| Python     | `@vz.vpoint(name=...)` + `vz.register(...)`                       | [Python SDK](/sdks/python)         |
| TypeScript | `@vpoint()` decorator or `createVPoints(namespace, api)`          | [TypeScript SDK](/sdks/typescript) |
| Go         | `varianz.VPoint(vz, name, fn)` or `varianz.Embed` + `vz.Register` | [Go SDK](/sdks/go)                 |
| Java       | `@VPoint(name = ...)` + annotation processor + agent              | [Java SDK](/sdks/java)             |
| Kotlin     | `@VPoint(name = ...)` + KSP processor + agent                     | [Kotlin SDK](/sdks/kotlin)         |

For the step-by-step walkthrough, see [Instrument a service](/guides/instrument-a-service).
