Docs / Operations
Metrics, memory and connections
What to scrape, how the memory budget works and how to size connections.
#Metrics
Every node serves Prometheus metrics at GET /metrics with the admin token. GET /status (gauntlet admin status) has the same and more as JSON. All metric names start with gauntlet_.
| Watch | Metric | Why |
|---|---|---|
| Is it serving | ready |
0 means the node is not ready |
| Which build | build_info{version, revision} |
Must be identical on every node |
| Refused connections | pg_rejected_connections_total{outcome} |
Above zero: the connection limit was hit |
| Memory pressure | memory_bytes{pool} against memory_limit_bytes{pool} |
A pool near its limit comes before 57P03 |
| Conflicts and unknown outcomes | sql_terminal_errors_total{code} |
40003 should be rare; each one needs a lookup |
| Bucket health | bucket_errors_total, bucket_throttled_total, bucket_request_duration_seconds{op} |
Commit latency follows the bucket |
| Stalled writes | shards_durable_io_stalled |
Above zero: a shard cannot write to the bucket |
| Ownership | shards{role}, ownership_changes_total{change} |
Long-lived recovering shards need attention |
| Checkpoints | checkpoint_lag_records |
Steady growth means checkpoints are not keeping up |
| Stuck transactions | prepared_oldest_age_seconds |
Should stay small |
| Databases | databases{state} |
How many are known and how many are resident |
- Gauntlet does not export process RSS, bucket size or object count. Collect RSS from the host and bucket figures from your provider.
- There are no published alert thresholds. Record a baseline under your normal load and alert on change.
- With
log-format = "json", each log line is one JSON object on stderr. Fields that look like secrets are redacted.
#Terms the console uses
| Term | Meaning |
|---|---|
| Window | An absolute start and end. Every figure states its window |
| As of | When the figure was last exported. A figure can be stale while the database is healthy |
| Unavailable | No export exists for the window. It is never shown as zero |
| Runtime share | A query pattern's total time divided by all patterns' total time in the window |
| Read amplification | Rows read divided by rows returned. A high value usually means a missing index |
Query Insights and per-database usage export are planned; today these figures come from node metrics.
#Memory budget
One setting controls memory: memory-mib. Every database the process hosts shares it.
| Case | Budget used |
|---|---|
You set memory-mib |
That value. Minimum 4096 |
| Not set, no container memory limit | 16384 MiB |
| Not set, smaller container limit | The container limit minus 1024 MiB |
| Not set, and that leaves less than 4096 MiB | The node refuses to start |
The budget is not a cap on the process's memory (RSS). It limits what Gauntlet reserves for its own work. On top of it, plan for the mapped block cache (cache-mib, default 8192), SQL buffers and the operating system.
When the budget is exhausted the node does not crash. It returns 57P03 (HTTP 503) and releases idle databases.
#Connections
Each node accepts 128 PostgreSQL connections by default. Set max-connections (1 to 10000) to change it; use the same value on every node.
- Starting and idle connections count. A connection with no traffic for 300 s is closed.
- One connection past the limit gets
FATAL 53300. - HTTP requests are not counted. They have their own queue; when it is full the answer is HTTP 503.
- Prefer a connection pool to a very large limit.