# Operations Guide

## Reliability Defaults

- Input validation is strict:
  - `doc_id` must be positive and within uint64 range.
  - embeddings must be non-empty and finite.
- Non-loopback targets require TLS.
- TLS client key/cert inputs must be provided as a pair when mTLS is used.
- API key validation rejects empty or control-character values.
- API keys can be rotated at runtime via:
  - `set_api_key(...)`
  - `set_api_key_provider(...)`
  - `set_api_key_provider_async(...)` (async client)

## Transport Defaults

The client applies conservative channel defaults suitable for long-lived production channels:

- `grpc.keepalive_time_ms=30000`
- `grpc.keepalive_timeout_ms=10000`
- `grpc.keepalive_permit_without_calls=1`
- `grpc.http2.max_pings_without_data=0`
- `grpc.max_receive_message_length=67108864`
- `grpc.max_send_message_length=67108864`

You can override any of these using `channel_options`.

Load-balancing policy:

- `lb_policy_name` maps to gRPC `grpc.lb_policy_name`.
- Keep this unset for single-endpoint deployments.
- Use explicit policy values (for example `round_robin`) only when target resolution returns multiple backends.

Connection reuse guidance:

- Reuse a single client/channel per worker process.
- Avoid per-request client construction.
- gRPC channels are multiplexed; concurrency should happen through shared client instances.

Unary batch controls:

- `max_unary_batch_size` (default `10000`) limits per-request ID fan-in for unary operations.
- `bulk_query` and `batch_delete_ids` automatically split large ID sets and aggregate responses.

## Retry Semantics

Read operations use retry with exponential backoff:

- `Query`
- `Search`
- `BulkQuery`
- `Health`
- `Metrics`
- `GetConfig`

Default retry policy:

- `max_attempts=3`
- `initial_backoff_s=0.05`
- `max_backoff_s=0.5`
- `multiplier=2.0`
- `jitter_ratio=0.2`
- `max_elapsed_time_s=2.0`
- retryable gRPC codes:
  - `UNAVAILABLE`
  - `DEADLINE_EXCEEDED`
  - `RESOURCE_EXHAUSTED`

Write paths (`Insert`, `Delete`, etc.) are not retried by default to avoid duplicate side effects.

Optional circuit breaker:

- Configure via `CircuitBreakerPolicy`.
- Failure tracking defaults to retryable transient codes (`UNAVAILABLE`, `DEADLINE_EXCEEDED`, `RESOURCE_EXHAUSTED`).
- Once open, calls fail fast with `CircuitOpenError` until recovery timeout elapses.

## Timeout Model

Each call accepts `timeout_s` to override the client default.

- if `timeout_s` is omitted, client `default_timeout_s` is used (defaults to `30.0s`)
- if `timeout_s` is `None`, the call is explicitly unbounded
- if `timeout_s` is set, it must be `> 0`

`wait_for_ready()` raises `DeadlineExceededError` on timeout.

## Error Mapping

gRPC transport errors are converted to typed SDK exceptions:

- `INVALID_ARGUMENT` -> `InvalidArgumentError`
- `UNAUTHENTICATED` -> `AuthenticationError`
- `PERMISSION_DENIED` -> `PermissionDeniedError`
- `NOT_FOUND` -> `NotFoundError`
- `RESOURCE_EXHAUSTED` -> `QuotaExceededError`
- `DEADLINE_EXCEEDED` -> `DeadlineExceededError`
- `UNAVAILABLE` -> `ServiceUnavailableError`
- `INTERNAL` / `DATA_LOSS` -> `InternalServerError`

Unknown codes map to base `KyroDBError`.

Security note:

- Error details are sanitized for common auth header patterns (`x-api-key`, `authorization`) before being exposed via SDK exceptions.

## Performance Notes

- If NumPy is installed (`pip install "kyrodb[numpy]"`), embedding validation uses a vectorized fast path.
- Without NumPy, validation uses a pure-Python fallback with the same correctness checks.
