> ## Documentation Index
> Fetch the complete documentation index at: https://pg-stat-ch-amogiska-arrow-instance-uuid.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> All pg_stat_ch GUC parameters with defaults, ranges, and reload behavior

pg\_stat\_ch is configured through PostgreSQL GUC (Grand Unified Configuration) parameters. All parameters use the `pg_stat_ch.` prefix.

## How to set parameters

Parameters can be set in `postgresql.conf`, via `ALTER SYSTEM`, or with `SET` (for session-level parameters only):

```ini theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
# postgresql.conf
pg_stat_ch.enabled = on
pg_stat_ch.flush_interval_ms = 500
pg_stat_ch.clickhouse_host = 'clickhouse.internal'
```

**Context** determines when a change takes effect:

| Context | When it takes effect | How to apply |
| - | - | - |
| `postmaster` | Server restart only | `systemctl restart postgresql` |
| `sighup` | Configuration reload | `SELECT pg_reload_conf();` or `pg_ctl reload` |
| `suset` | Superuser SET | `SET pg_stat_ch.param = value;` |

## General

### `pg_stat_ch.enabled`

Enable or disable query telemetry collection.

| | |
| - | - |
| **Type** | boolean |
| **Default** | `on` |
| **Context** | sighup |

When disabled, hooks still fire but skip event creation. The background worker continues running but has nothing to export. Use this to temporarily pause collection without restarting PostgreSQL.

```sql theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
-- Disable collection (takes effect immediately after reload)
ALTER SYSTEM SET pg_stat_ch.enabled = off;
SELECT pg_reload_conf();

-- Re-enable
ALTER SYSTEM SET pg_stat_ch.enabled = on;
SELECT pg_reload_conf();
```

### `pg_stat_ch.hostname`

Override the machine hostname sent with events.

| | |
| - | - |
| **Type** | string |
| **Default** | `''` (empty, uses system hostname) |
| **Context** | postmaster |

Useful in containerized environments where the system hostname is a random container ID. Set this to a stable identifier like the pod name or instance ID.

### `pg_stat_ch.extra_attributes`

Exporter metadata expressed as semicolon-separated `key:value` pairs. `instance_uuid` is included in all export formats; the other resource columns are populated by the Arrow exporters.

| | |
| - | - |
| **Type** | string |
| **Default** | `''` |
| **Context** | sighup |

Supply `instance_uuid` with the Postgres service's canonical UUID alongside the existing `instance_ubid` and server attributes:

```ini theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
pg_stat_ch.extra_attributes = 'instance_uuid:01234567-89ab-8ad0-9234-56789abcdef0;instance_ubid:pg04hmasw9ne4j8t5cy4tqkff1;server_role:primary'
```

The provisioner supplies the UUID; the producer does not derive it from the UBID. Native ClickHouse and Arrow exports include an `instance_uuid` string column, and ordinary OTLP exports include an `instance_uuid` log attribute. An omitted value produces an empty string.

The bundled ClickHouse migration adds `instance_uuid String DEFAULT ''` to `events_raw`. Apply it **before deploying the producer when using native ClickHouse export**: its named inserts require the column even when the UUID is unset. ArrowStream inserts can arrive before the column exists; ClickHouse ignores the extra field until the schema includes it. External schemas and materialized-view projections need their own updates to retain the UUID; previously ignored values are not backfilled.

### `pg_stat_ch.log_min_elevel`

Minimum error severity level to capture via the `emit_log_hook`.

| | |
| - | - |
| **Type** | enum |
| **Default** | `warning` |
| **Context** | suset |
| **Values** | `debug5`, `debug4`, `debug3`, `debug2`, `debug1`, `log`, `info`, `notice`, `warning`, `error`, `fatal`, `panic` |

Controls which PostgreSQL log messages are captured as events. The default (`warning`) captures warnings, errors, fatals, and panics. Set to `error` to skip warnings, or `debug5` to capture everything.

```sql theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
-- Capture only errors and above
SET pg_stat_ch.log_min_elevel = 'error';

-- Capture everything including debug messages (noisy)
SET pg_stat_ch.log_min_elevel = 'debug5';
```

### `pg_stat_ch.min_duration_us`

Minimum query duration in microseconds to always capture.

| | |
| - | - |
| **Type** | integer |
| **Default** | `0` (capture all) |
| **Min** | `0` |
| **Max** | `2147483647` |
| **Context** | suset |

Queries with duration at or above this threshold are always captured. Queries below this threshold are sampled at `sample_rate`. Set to `0` to capture all queries unconditionally (subject to `sample_rate`).

```sql theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
-- Only guarantee capture of queries taking >= 1ms
ALTER SYSTEM SET pg_stat_ch.min_duration_us = 1000;
SELECT pg_reload_conf();

-- Per-session override for debugging
SET pg_stat_ch.min_duration_us = 0;
```

### `pg_stat_ch.sample_rate`

Sampling rate for queries below `min_duration_us`.

| | |
| - | - |
| **Type** | real |
| **Default** | `1.0` (capture all) |
| **Min** | `0.0` |
| **Max** | `1.0` |
| **Context** | suset |

Fraction of sub-threshold queries to randomly capture. Queries at or above `min_duration_us` are always captured regardless of this setting.

```sql theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
-- Capture all queries >= 500us, sample 10% of faster queries
ALTER SYSTEM SET pg_stat_ch.min_duration_us = 500;
ALTER SYSTEM SET pg_stat_ch.sample_rate = 0.1;
SELECT pg_reload_conf();

-- Drop all sub-threshold queries (hard cutoff)
ALTER SYSTEM SET pg_stat_ch.sample_rate = 0.0;
SELECT pg_reload_conf();
```

## Queue

The shared-memory ring buffer sits between the foreground hooks and the background worker. These settings control its size and drain behavior.

### `pg_stat_ch.queue_capacity`

Maximum number of events the ring buffer can hold.

| | |
| - | - |
| **Type** | integer |
| **Default** | `131072` (128K events) |
| **Min** | `1024` |
| **Max** | `4194304` (4M events) |
| **Context** | postmaster |

Must be a power of 2 (1024, 2048, 4096, ... 4194304). The ring buffer uses bitmask arithmetic for slot indexing, which requires a power-of-2 capacity.

Each ring slot is about 520 bytes on 64-bit platforms; query and error text live in the DSA string area rather than in the slot. The default capacity of 131072 events uses about **68 MB** for slots, on top of `pg_stat_ch.string_area_size` (64 MB by default) and an interner hash table sized to the same capacity. Adjust based on your query throughput and acceptable memory usage.

<Warning>
  Changing this parameter requires a PostgreSQL restart.
</Warning>

**Sizing guidance:**

| Workload | QPS | Recommended capacity | Ring slot memory |
| - | - | - | - |
| Low traffic | \< 1,000 | 8192 | \~4 MB |
| Medium traffic | 1,000 - 10,000 | 65536 | \~34 MB |
| High traffic | 10,000 - 100,000 | 131072 (default) | \~68 MB |
| Very high traffic | > 100,000 | 524288+ | \~273 MB+ |

The queue needs to hold enough events to buffer a burst while the background worker flushes a batch. If `dropped_events` in `pg_stat_ch_stats()` is non-zero, increase this value.

### `pg_stat_ch.flush_interval_ms`

Interval between export batches, in milliseconds.

| | |
| - | - |
| **Type** | integer |
| **Default** | `500` |
| **Min** | `100` |
| **Max** | `60000` |
| **Context** | sighup |
| **Unit** | milliseconds |

The background worker sleeps for this duration between drain cycles. Lower values reduce latency from query execution to ClickHouse visibility. Higher values reduce the number of ClickHouse inserts (fewer, larger batches).

### `pg_stat_ch.batch_max`

Maximum number of events per ClickHouse insert.

| | |
| - | - |
| **Type** | integer |
| **Default** | `131072` |
| **Min** | `1` |
| **Max** | `1000000` |
| **Context** | sighup |

Limits the size of each batch sent to ClickHouse. The background worker drains up to `batch_max` events per insert, then loops until the queue is empty or below the threshold.

Values above `pg_stat_ch.queue_capacity` are clamped: one drain pass cannot yield more events than the ring buffer holds. The dequeue buffer is sized to the events actually queued, roughly 4.6 KB each, so a full-queue drain at the default peaks near 600 MB in the worker.

## ClickHouse connection

These parameters configure the connection to ClickHouse. All require a PostgreSQL restart to take effect.

### `pg_stat_ch.clickhouse_host`

ClickHouse server hostname.

| | |
| - | - |
| **Type** | string |
| **Default** | `localhost` |
| **Context** | postmaster |

### `pg_stat_ch.clickhouse_port`

ClickHouse native protocol port.

| | |
| - | - |
| **Type** | integer |
| **Default** | `9000` |
| **Min** | `1` |
| **Max** | `65535` |
| **Context** | postmaster |

This is the native TCP protocol port, not the HTTP port (8123). The native protocol is more efficient for bulk inserts.

### `pg_stat_ch.clickhouse_user`

ClickHouse username.

| | |
| - | - |
| **Type** | string |
| **Default** | `default` |
| **Context** | postmaster |

### `pg_stat_ch.clickhouse_password`

ClickHouse password.

| | |
| - | - |
| **Type** | string |
| **Default** | `''` (empty) |
| **Context** | postmaster |

<Note>
  This parameter is restricted to superusers (`GUC_SUPERUSER_ONLY`). It is not visible via `SHOW` to non-superuser roles.
</Note>

### `pg_stat_ch.clickhouse_database`

ClickHouse database name where the `events_raw` table and materialized views live.

| | |
| - | - |
| **Type** | string |
| **Default** | `pg_stat_ch` |
| **Context** | postmaster |

### `pg_stat_ch.clickhouse_use_tls`

Enable TLS encryption for ClickHouse connections.

| | |
| - | - |
| **Type** | boolean |
| **Default** | `off` |
| **Context** | postmaster |

### `pg_stat_ch.clickhouse_skip_tls_verify`

Skip TLS certificate verification.

| | |
| - | - |
| **Type** | boolean |
| **Default** | `off` |
| **Context** | postmaster |

<Warning>
  Only use this for testing. In production, configure proper TLS certificates.
</Warning>

## OpenTelemetry

These parameters configure the OpenTelemetry export backend. Enable it with `pg_stat_ch.use_otel = on`. When OTel mode is active, events are sent as OpenTelemetry logs instead of ClickHouse inserts.

### `pg_stat_ch.use_otel`

Send events via OpenTelemetry instead of ClickHouse.

| | |
| - | - |
| **Type** | boolean |
| **Default** | `off` |
| **Context** | postmaster |

When enabled, the background worker sends events to an OTel collector via gRPC instead of inserting into ClickHouse. The ClickHouse connection parameters are ignored.

### `pg_stat_ch.otel_endpoint`

OpenTelemetry gRPC endpoint.

| | |
| - | - |
| **Type** | string |
| **Default** | `localhost:4317` |
| **Context** | postmaster |

The `host:port` of the OTel collector's gRPC receiver. Port 4317 is the standard OTel gRPC port.

### `pg_stat_ch.otel_log_queue_size`

Compatibility setting for legacy OTel queue sizing.

| | |
| - | - |
| **Type** | integer |
| **Default** | `65536` |
| **Min** | `512` |
| **Max** | `1048576` |
| **Context** | postmaster |

The direct OTLP exporter uses pg\_stat\_ch's shared-memory queue instead of allocating a second OTel queue, so this setting is retained for compatibility only.

### `pg_stat_ch.otel_log_batch_size`

Maximum records per OTLP log export call.

| | |
| - | - |
| **Type** | integer |
| **Default** | `8192` |
| **Min** | `1` |
| **Max** | `131072` |
| **Context** | postmaster |

Caps how many log records the direct OTLP exporter puts into a single `ExportLogs` request.

### `pg_stat_ch.otel_log_max_bytes`

Soft byte budget in bytes for a single OTLP log export call.

| | |
| - | - |
| **Type** | integer |
| **Default** | `3145728` (3 MiB) |
| **Min** | `65536` (64 KiB) |
| **Max** | `67108864` (64 MiB) |
| **Context** | postmaster |
| **Unit** | bytes |

The direct OTLP exporter chunks log records to stay under this per-request budget. The gRPC default maximum is 4 MiB, so the default value of 3 MiB leaves a safety margin.

### `pg_stat_ch.otel_log_delay_ms`

Deadline for a single OTLP log export call.

| | |
| - | - |
| **Type** | integer |
| **Default** | `100` |
| **Min** | `10` |
| **Max** | `60000` |
| **Context** | postmaster |
| **Unit** | milliseconds |

The direct OTLP exporter uses this as the per-request gRPC timeout so the bgworker cannot block indefinitely on a slow collector.

### `pg_stat_ch.otel_metric_interval_ms`

Compatibility setting for legacy OTel metric export interval.

| | |
| - | - |
| **Type** | integer |
| **Default** | `5000` |
| **Min** | `100` |
| **Max** | `300000` |
| **Context** | postmaster |
| **Unit** | milliseconds |

The direct OTLP exporter currently sends logs only, so this setting has no effect.

## Debug

These parameters are for development and testing only.

### `pg_stat_ch.debug_force_locked_overflow`

Force the overflow code path in the locked enqueue path.

| | |
| - | - |
| **Type** | boolean |
| **Default** | `off` |
| **Context** | suset |

Used to deterministically test the overflow-under-lock deadlock fix. Do not enable in production.
