> For the complete documentation index, see [llms.txt](https://cantonindexer.infradao.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cantonindexer.infradao.com/kubernetes.md).

# Kubernetes suggestions

These are suggestions for running the node in Kubernetes, not a supported chart. Each names the behaviour of the node that motivates it. The settings themselves are in [Install](/install.md#run-the-node) and [Tutorial: run the server](/server.md).

**One replica per store, `strategy: Recreate`.** One node per store is all the node supports today; several nodes on one store is deferred (#188). A second replica would run every filter twice against one store, and the default `RollingUpdate` starts the new pod before the old one stops, so for a moment two nodes share the store. `Recreate` stops the old pod first.

```yaml
spec:
  replicas: 1
  strategy:
    type: Recreate
```

**`terminationGracePeriodSeconds` above `SHUTDOWN_GRACE_SECS`.** On `SIGTERM` the node waits for open gRPC connections to close, then gives filter tasks `SHUTDOWN_GRACE_SECS` (default 60) to stop, then closes its connection pool. The pod's grace period has to cover all three, and a metrics scrape in progress. Kubernetes' default of 30 s is below the node's default of 60. InfraDAO's DevNet deployment sets 90. A kill past it loses nothing committed: the batch in progress is redone from the cursor at the next boot.

**Secrets for `DB_PASSWORD` and `PQS_URL`.** Both carry a password. Read them with `valueFrom.secretKeyRef`. In `PQS_URL`, a password with a character that has a meaning in a URL, such as `@`, `:` or `/`, must be percent-encoded.

```yaml
env:
  - name: NO_AUTH_GRPC_ADDR
    value: "0.0.0.0:8020"
  - name: DB_PASSWORD
    valueFrom: { secretKeyRef: { name: indexer-store, key: password } }
  - name: PQS_URL
    valueFrom: { secretKeyRef: { name: indexer-pqs, key: url } }
```

**gRPC behind a ClusterIP Service only.** The management service has no authentication: whoever reaches it can deploy, or replace a filter and drop its documents. Its default address, `127.0.0.1:8020`, is the pod's loopback, which a Service cannot reach, so set `NO_AUTH_GRPC_ADDR=0.0.0.0:8020` and expose port 8020 through a `ClusterIP` Service only, never a `LoadBalancer` or `NodePort`. Reach it with `kubectl port-forward` and `node = "http://127.0.0.1:8020"`. An ingress adds TLS, not authentication ([Install](/install.md#run-the-node)).

**Metrics scraping on 9464.** The node serves Prometheus metrics at `/metrics` on `0.0.0.0:9464` (`METRICS_ADDR`), without authentication. Name the container port `metrics` and point a scrape config or a `PodMonitor` at it. Each scrape counts the registry's filters in the store, within 3 s.

**Probes.** The node has no health endpoint; `/metrics` is its only HTTP route. Suggested: no liveness probe, and a TCP readiness probe on 9464. The node exits with code 1 when boot fails and when its filter runtime ends, so Kubernetes restarts it without a probe. It binds 9464 only after the migrations ran and PQS was reached, so the TCP probe passes once those two have.

```yaml
readinessProbe:
  tcpSocket: { port: 9464 }
  periodSeconds: 10
```

**Resources.** There are no measured sizing figures. InfraDAO's DevNet deployment requests `cpu: 100m` and `memory: 128Mi` and limits memory to `512Mi`. A `select` expression has no memory limit, and one that runs out of memory ends the whole process.

## Sources

* canton-indexer v0.10.0, released 2026-10-22 (<https://github.com/InfraDAO/canton-indexer-releases/releases/tag/v0.10.0>): `rules.toml` `[deferrals]` (#188), `crates/indexer/src/main.rs`, `node.rs` and `metrics.rs`, `docs/runtime.md`, decision 0007, README "Node" (the grace period covers a scrape in progress).
* Percent-encoding in a Postgres connection URI: <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS>
* InfraDAO DevNet deployment (node `v0.9.0`), indexer-argocd `canton/devnet/config/indexer/indexer.yaml`, read 2026-10-22.
* Kubernetes: <https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination>, <https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy>
