diff --git a/config/config.md b/config/config.md
index 29f2d6d2c56..33ca160a3b1 100644
--- a/config/config.md
+++ b/config/config.md
@@ -16,17 +16,16 @@
| `default_column_prefix` | String | Unset | The default column prefix for auto-created time index, value, and native histogram columns.
Legacy OTLP summary columns keep their historical `greptime_` prefix. |
| `auto_create_table` | Bool | `true` | Server-side global switch for auto table creation on write.
When `false`, a missing table is never auto-created even if the request sets the `auto_create_table` hint to `true`. Default: `true`. |
| `experimental_metric_export` | Bool | `false` | Enables experimental Parquet COPY DATABASE using shared Metric physical scans.
Resume requires the previous export and storage writes to have ended; HTTP timeout is not confirmation. |
-| `user_provider` | String | Unset | The user provider for authentication.
Examples: "static_user_provider:file:/path/to/users", "static_user_provider:cmd:greptime_user=greptime_pwd"
Password verifier formats: "plain:", "pbkdf2_sha256:::",
"mysql_native_password:",
"pg_scram_sha256::::"
"pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but cannot authenticate over MySQL's
native password handshake; a MySQL client must send the password in cleartext for such users.
"mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
"mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
For "pg_scram_sha256" users, keep the default iteration count (4096) and salt length (16): both are
observable in the SCRAM server-first message, and non-default values weaken resistance to username
enumeration. |
-| `max_in_flight_write_bytes` | String | Unset | Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
Set to 0 to disable the limit. Default: "0" (unlimited) |
-| `write_bytes_exhausted_policy` | String | Unset | Policy when write bytes quota is exhausted.
Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail" |
+| `user_provider` | String | Unset | The user provider for authentication.
Examples: "static_user_provider:file:/path/to/users", "static_user_provider:cmd:greptime_user=greptime_pwd"
Password verifier formats: "plain:", "pbkdf2_sha256:::",
"mysql_native_password:",
"pg_scram_sha256::::"
"pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but such users cannot log in over MySQL:
`static_user_provider` and `watch_file_user_provider` only negotiate `mysql_native_password`, which cannot verify these formats.
"mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
"mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
For "pg_scram_sha256" users, keep the default iteration count (4096) and salt length (16): both are
observable in the SCRAM server-first message, and non-default values weaken resistance to username
enumeration. |
+| `max_in_flight_write_bytes` | String | 0 | Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
Set to 0 to disable the limit. Default: "0" (unlimited) |
+| `write_bytes_exhausted_policy` | String | `wait` | Policy when write bytes quota is exhausted.
Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail" |
| `init_regions_in_background` | Bool | `false` | Initialize all regions in the background during the startup.
By default, it provides services after all regions have been initialized. |
| `init_regions_parallelism` | Integer | `16` | Parallelism of initializing regions. |
-| `max_concurrent_queries` | Integer | `0` | The maximum concurrent queries allowed to be executed. Zero means unlimited. |
| `enable_telemetry` | Bool | `true` | Enable telemetry to collect anonymous usage data. Enabled by default. |
| `runtime` | -- | -- | The runtime options. |
-| `runtime.global_rt_size` | Integer | `8` | The number of threads to execute the runtime for global read operations. |
-| `runtime.compact_rt_size` | Integer | `4` | The number of threads to execute compact operations. |
-| `runtime.compact_rt_max_blocking_threads` | Integer | `4` | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.global_rt_size` | Integer | Auto | The number of threads to execute the runtime for global read operations.
Defaults to max(num_cpus, 2). |
+| `runtime.compact_rt_size` | Integer | Auto | The number of threads to execute compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.compact_rt_max_blocking_threads` | Integer | Auto | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
| `runtime.experimental_workload_scheduler` | -- | -- | Experimental weighted, work-conserving query/write task scheduler. |
| `runtime.experimental_workload_scheduler.enable` | Bool | `false` | Enable when concurrent queries and writes interfere with each other—for example, when long-running queries increase ingestion latency.
The weights set their relative runtime shares while both are backlogged. Disabled by default. |
| `runtime.experimental_workload_scheduler.query_weight` | Integer | `2` | Relative query share while both query and write workloads are backlogged. |
@@ -110,7 +109,7 @@
| `wal.enable_log_recycle` | Bool | `true` | Whether to reuse logically truncated log files.
**It's only used when the provider is `raft_engine`**. |
| `wal.prefill_log_files` | Bool | `false` | Whether to pre-create log files on start up.
**It's only used when the provider is `raft_engine`**. |
| `wal.sync_period` | String | `5s` | Duration for fsyncing log files.
**It's only used when the provider is `raft_engine`**. |
-| `wal.recovery_parallelism` | Integer | `2` | Parallelism during WAL recovery. |
+| `wal.recovery_parallelism` | Integer | Auto | Parallelism during WAL recovery. Defaults to the number of CPU cores; this example sets it to 2. |
| `wal.broker_endpoints` | Array | -- | The Kafka broker endpoints.
**It's only used when the provider is `kafka`**. |
| `wal.connect_timeout` | String | `3s` | The connect timeout for kafka client.
**It's only used when the provider is `kafka`**. |
| `wal.timeout` | String | `5s` | The total request timeout for kafka client.
**It's only used when the provider is `kafka`**. |
@@ -140,7 +139,7 @@
| `procedure.max_running_procedures` | Integer | `128` | Max running procedures.
The maximum number of procedures that can be running at the same time.
If the number of running procedures exceeds this limit, the procedure will be rejected. |
| `query` | -- | -- | The query engine options. |
| `query.parallelism` | Integer | `0` | Parallelism of the query engine.
Default to 0, which means the number of CPU cores. |
-| `query.memory_pool_size` | String | `50%` | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit (unbounded, default behavior).
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
+| `query.memory_pool_size` | String | 0 | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
| `query.experimental_memory_pool_policy` | String | `greedy` | Experimental memory pool allocation policy:
- "greedy" (default): first-come-first-served allocation; preserves current behavior.
- "fair": divides available memory among spillable operators and may spill earlier.
Only effective when `memory_pool_size` is bounded (>0). |
| `query.experimental_spill_mode` | String | `default` | Spill mode:
- "default": preserve DataFusion built-in OS temp directory (default).
- "custom": explicitly configure spill path, quota, and compression.
- "disabled": explicitly disable disk spilling.
Set this to "custom" before using the path/quota/compression keys below. |
| `query.experimental_spill_path` | String | Unset | Spill directory path. Ignored unless mode is "custom". |
@@ -174,7 +173,7 @@
| `storage.http_client.skip_ssl_validation` | Bool | `false` | To skip the ssl verification
**Security Notice**: Setting `skip_ssl_validation = true` disables certificate verification, making connections vulnerable to man-in-the-middle attacks. Only use this in development or trusted private networks. |
| `[[region_engine]]` | -- | -- | The region engine options. You can configure multiple region engines.
Each engine type (mito, file, metric) may appear only once; duplicates cause startup to fail. |
| `region_engine.mito` | -- | -- | The Mito engine options. |
-| `region_engine.mito.num_workers` | Integer | `8` | Number of region workers. |
+| `region_engine.mito.num_workers` | Integer | Auto | Number of region workers. Defaults to half of the available CPU cores, rounded up. |
| `region_engine.mito.worker_channel_size` | Integer | `128` | Request channel size of each worker. |
| `region_engine.mito.worker_request_batch_size` | Integer | `64` | Max batch size for a worker to handle requests. |
| `region_engine.mito.manifest_checkpoint_distance` | Integer | `10` | Number of meta action updated to trigger a new checkpoint for the manifest. |
@@ -258,17 +257,18 @@
| `logging.tracing_sample_ratio` | -- | Unset | The percentage of tracing will be sampled and exported.
Valid range `[0, 1]`, 1 means all traces are sampled, 0 means all traces are not sampled, the default value is 1.
ratio > 1 are treated as 1. Fractions < 0 are treated as 0 |
| `logging.tracing_sample_ratio.default_ratio` | Float | `1.0` | -- |
| `slow_query` | -- | -- | The slow query log options. |
-| `slow_query.enable` | Bool | `false` | Whether to enable slow query log. |
-| `slow_query.record_type` | String | Unset | The record type of slow queries. It can be `system_table` or `log`. |
-| `slow_query.threshold` | String | Unset | The threshold of slow query. |
-| `slow_query.sample_ratio` | Float | Unset | The sampling ratio of slow query log. The value should be in the range of (0, 1]. |
+| `slow_query.enable` | Bool | `true` | Whether to enable slow query log. |
+| `slow_query.record_type` | String | `system_table` | The record type of slow queries. It can be `system_table` or `log`.
If `system_table` is selected, the slow queries will be recorded in a system table `greptime_private.slow_queries`.
If `log` is selected, the slow queries will be logged in a log file `greptimedb-slow-queries.*`. |
+| `slow_query.threshold` | String | `30s` | The threshold of slow query. It can be human readable time string, for example: `10s`, `100ms`, `1s`. |
+| `slow_query.sample_ratio` | Float | `1.0` | The sampling ratio of slow query log. The value should be in the range of (0, 1]. For example, `0.1` means 10% of the slow queries will be logged and `1.0` means all slow queries will be logged. |
+| `slow_query.ttl` | String | `90d` | The TTL of the `slow_queries` system table. Default is `90d` when `record_type` is `system_table`. |
| `tracing` | -- | -- | The tracing options. Only effect when compiled with `tokio-console` feature. |
| `tracing.tokio_console_addr` | String | Unset | The tokio console address. |
| `pipeline` | -- | -- | The pipeline options. |
| `pipeline.cache_ttl` | String | `10s` | Time to live of the local pipeline cache. Default is `10s`. |
| `event_recorder` | -- | -- | Configuration options for the event recorder. |
| `event_recorder.ttl` | String | `90d` | TTL for the events table that will be used to store the events. Default is `90d`. |
-| `event_recorder.event_types` | Array | -- | Event types to record. Current available event types: `create_database`,
`alter_database`, `drop_database`, `create_flow`, `drop_flow`,
`create_table`, `create_logical_tables`, `alter_table`, `alter_logical_tables`,
`drop_table`, `undrop_table`, `purge_dropped_table`, `truncate_table`,
`create_view`, `drop_view`, `admin_function`, `reconcile_catalog`,
`reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
+| `event_recorder.event_types` | Array | All | Event types to record. Current available event types: `create_database`,
`alter_database`, `drop_database`, `create_flow`, `drop_flow`,
`create_table`, `create_logical_tables`, `alter_table`, `alter_logical_tables`,
`drop_table`, `undrop_table`, `purge_dropped_table`, `truncate_table`,
`create_view`, `drop_view`, `admin_function`, `reconcile_catalog`,
`reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
| `memory` | -- | -- | The memory options. |
| `memory.enable_heap_profiling` | Bool | `true` | Whether to enable heap profiling activation during startup.
When enabled, heap profiling will be activated if the `MALLOC_CONF` environment variable
is set to "prof:true,prof_active:false". The official image adds this env variable.
Default is true. |
@@ -283,13 +283,13 @@
| `default_column_prefix` | String | Unset | The default column prefix for auto-created time index, value, and native histogram columns.
Legacy OTLP summary columns keep their historical `greptime_` prefix. |
| `auto_create_table` | Bool | `true` | Server-side global switch for auto table creation on write.
When `false`, a missing table is never auto-created even if the request sets the `auto_create_table` hint to `true`. Default: `true`. |
| `experimental_metric_export` | Bool | `false` | Enables experimental Parquet COPY DATABASE using shared Metric physical scans.
Resume requires the previous export and storage writes to have ended; HTTP timeout is not confirmation. |
-| `user_provider` | String | Unset | The user provider for authentication.
Examples: "static_user_provider:file:/path/to/users", "static_user_provider:cmd:greptime_user=greptime_pwd"
Password verifier formats: "plain:", "pbkdf2_sha256:::",
"mysql_native_password:",
"pg_scram_sha256::::"
"pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but cannot authenticate over MySQL's
native password handshake; a MySQL client must send the password in cleartext for such users.
"mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
"mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
For "pg_scram_sha256" users, keep the default iteration count (4096) and salt length (16): both are
observable in the SCRAM server-first message, and non-default values weaken resistance to username
enumeration. |
-| `max_in_flight_write_bytes` | String | Unset | Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
Set to 0 to disable the limit. Default: "0" (unlimited) |
-| `write_bytes_exhausted_policy` | String | Unset | Policy when write bytes quota is exhausted.
Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail" |
+| `user_provider` | String | Unset | The user provider for authentication.
Examples: "static_user_provider:file:/path/to/users", "static_user_provider:cmd:greptime_user=greptime_pwd"
Password verifier formats: "plain:", "pbkdf2_sha256:::",
"mysql_native_password:",
"pg_scram_sha256::::"
"pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but such users cannot log in over MySQL:
`static_user_provider` and `watch_file_user_provider` only negotiate `mysql_native_password`, which cannot verify these formats.
"mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
"mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
For "pg_scram_sha256" users, keep the default iteration count (4096) and salt length (16): both are
observable in the SCRAM server-first message, and non-default values weaken resistance to username
enumeration. |
+| `max_in_flight_write_bytes` | String | 0 | Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
Set to 0 to disable the limit. Default: "0" (unlimited) |
+| `write_bytes_exhausted_policy` | String | `wait` | Policy when write bytes quota is exhausted.
Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail" |
| `runtime` | -- | -- | The runtime options. |
-| `runtime.global_rt_size` | Integer | `8` | The number of threads to execute the runtime for global read operations. |
-| `runtime.compact_rt_size` | Integer | `4` | The number of threads to execute compact operations. |
-| `runtime.compact_rt_max_blocking_threads` | Integer | `4` | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.global_rt_size` | Integer | Auto | The number of threads to execute the runtime for global read operations.
Defaults to max(num_cpus, 2). |
+| `runtime.compact_rt_size` | Integer | Auto | The number of threads to execute compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.compact_rt_max_blocking_threads` | Integer | Auto | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
| `http` | -- | -- | The HTTP server options. |
| `http.addr` | String | `127.0.0.1:4000` | The address to bind the HTTP server. |
| `http.timeout` | String | `0s` | HTTP request timeout. Set to 0 to disable timeout.
When synchronous Prometheus, OTLP metrics, or ordinary-table batching is enabled, a nonzero timeout is
raised to at least the largest active flush interval plus 1 second. The intervals come from
`pending_rows_batcher.logical_table.pending_rows_flush_interval` and `pending_rows_batcher.pending_rows_flush_interval`. |
@@ -300,20 +300,20 @@
| `http.api_server_addr` | String | `127.0.0.1:4006` | The address to bind the dedicated HTTP API server, in the same form as `addr`.
Defaults to `127.0.0.1:4006`. |
| `grpc` | -- | -- | The gRPC server options. |
| `grpc.bind_addr` | String | `127.0.0.1:4001` | The address to bind the gRPC server. |
-| `grpc.server_addr` | String | `127.0.0.1:4001` | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
+| `grpc.server_addr` | String | Unset | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
| `grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
-| `grpc.flight_compression` | String | `arrow_ipc` | Compression mode for frontend side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `none` |
+| `grpc.flight_compression` | String | `arrow_ipc` | Compression mode for frontend side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `arrow_ipc`. |
| `grpc.max_connection_age` | String | Unset | The maximum connection age for gRPC connection.
The value can be a human-readable time string. For example: `10m` for ten minutes or `1h` for one hour.
Refer to https://grpc.io/docs/guides/keepalive/ for more details. |
| `grpc.tls` | -- | -- | gRPC server TLS options, see `mysql.tls` section. |
| `grpc.tls.mode` | String | `disable` | TLS mode. |
| `grpc.tls.cert_path` | String | Unset | Certificate file path. |
| `grpc.tls.key_path` | String | Unset | Private key file path. |
| `grpc.tls.watch` | Bool | `false` | Watch for Certificate and key file change and auto reload.
For now, gRPC tls config does not support auto reload. |
-| `internal_grpc` | -- | -- | The internal gRPC server options. Internal gRPC port for nodes inside cluster to access frontend. |
-| `internal_grpc.bind_addr` | String | `127.0.0.1:4010` | The address to bind the gRPC server. |
-| `internal_grpc.server_addr` | String | `127.0.0.1:4010` | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `internal_grpc.bind_addr`. |
+| `internal_grpc` | -- | -- | The internal gRPC server options. Internal gRPC port for nodes inside cluster to access frontend.
The internal gRPC server starts only when this section is set. |
+| `internal_grpc.bind_addr` | String | Unset | The address to bind the gRPC server.
If unset, it falls back to `127.0.0.1:4001`, the same address as `grpc.bind_addr`. |
+| `internal_grpc.server_addr` | String | Unset | The address advertised to the metasrv, and used for connections from outside the host.
Unlike `grpc.server_addr`, it is not detected automatically; set it explicitly. |
| `internal_grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
-| `internal_grpc.flight_compression` | String | `arrow_ipc` | Compression mode for frontend side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `none` |
+| `internal_grpc.flight_compression` | String | `arrow_ipc` | Compression mode for frontend side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `arrow_ipc`. |
| `internal_grpc.tls` | -- | -- | internal gRPC server TLS options, see `mysql.tls` section. |
| `internal_grpc.tls.mode` | String | `disable` | TLS mode. |
| `internal_grpc.tls.cert_path` | String | Unset | Certificate file path. |
@@ -381,7 +381,7 @@
| `query` | -- | -- | The query engine options. |
| `query.parallelism` | Integer | `0` | Parallelism of the query engine.
Default to 0, which means the number of CPU cores. |
| `query.allow_query_fallback` | Bool | `false` | Whether to allow query fallback when push down optimize fails.
Default to false, meaning when push down optimize failed, return error msg |
-| `query.memory_pool_size` | String | `50%` | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "4GB", "8GB") or percentage of system memory (e.g., "30%").
Setting it to 0 disables the limit (unbounded, default behavior).
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans (only applies to datanodes). |
+| `query.memory_pool_size` | String | 0 | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "4GB", "8GB") or percentage of system memory (e.g., "30%").
Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans (only applies to datanodes). |
| `query.experimental_memory_pool_policy` | String | `greedy` | Experimental memory pool allocation policy:
- "greedy" (default): first-come-first-served allocation; preserves current behavior.
- "fair": divides available memory among spillable operators and may spill earlier.
Only effective when `memory_pool_size` is bounded (>0). |
| `query.experimental_spill_mode` | String | `default` | Spill mode:
- "default": preserve DataFusion built-in OS temp directory (default).
- "custom": explicitly configure spill path, quota, and compression.
- "disabled": explicitly disable disk spilling.
Set this to "custom" before using the path/quota/compression keys below. |
| `query.experimental_spill_path` | String | Unset | Spill directory path. Ignored unless mode is "custom". |
@@ -389,7 +389,7 @@
| `query.experimental_spill_compression` | String | `uncompressed` | Compression for spilled data files: "uncompressed" (default), "lz4_frame", "zstd".
Ignored unless mode is "custom". |
| `datanode` | -- | -- | Datanode options. |
| `datanode.client` | -- | -- | Datanode client options. |
-| `datanode.client.connect_timeout` | String | `10s` | -- |
+| `datanode.client.connect_timeout` | String | 1s | Connect server timeout. Defaults to `1s`; this example sets it to `10s`. |
| `datanode.client.tcp_nodelay` | Bool | `true` | -- |
| `datanode.client.max_recv_message_size` | String | `512MB` | The maximum receive message size for the gRPC client. |
| `datanode.client.max_send_message_size` | String | `512MB` | The maximum send message size for the gRPC client. |
@@ -422,7 +422,7 @@
| `pipeline.cache_ttl` | String | `10s` | Time to live of the frontend-local pipeline cache. A pipeline created or deleted on
another frontend takes effect on this one after at most this duration. |
| `event_recorder` | -- | -- | Configuration options for the event recorder. |
| `event_recorder.ttl` | String | `90d` | TTL for the events table that will be used to store the events. Default is `90d`. |
-| `event_recorder.event_types` | Array | -- | Event types to record. Current available event type: `admin_function`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
+| `event_recorder.event_types` | Array | All | Event types to record. Current available event type: `admin_function`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
### Metasrv
@@ -434,7 +434,7 @@
| `store_key_prefix` | String | `""` | If it's not empty, the metasrv will store all data with this key prefix. |
| `backend` | String | `etcd_store` | The datastore for meta server.
Available values:
- `etcd_store` (default value)
- `memory_store`
- `postgres_store`
- `mysql_store` |
| `meta_table_name` | String | `greptime_metakv` | Table name in RDS to store metadata. Effect when using a RDS kvbackend.
**Only used when backend is `postgres_store`.** |
-| `meta_schema_name` | String | `greptime_schema` | Optional PostgreSQL schema for metadata table and election table name qualification.
When PostgreSQL public schema is not writable (e.g., PostgreSQL 15+ with restricted public),
set this to a writable schema. GreptimeDB will use `meta_schema_name`.`meta_table_name`.
**Only used when backend is `postgres_store`.** |
+| `meta_schema_name` | String | Unset | Optional PostgreSQL schema for metadata table and election table name qualification.
When PostgreSQL public schema is not writable (e.g., PostgreSQL 15+ with restricted public),
set this to a writable schema. GreptimeDB will use `meta_schema_name`.`meta_table_name`.
**Only used when backend is `postgres_store`.**
Unset by default; this example sets it to `greptime_schema`. |
| `auto_create_schema` | Bool | `true` | Automatically create PostgreSQL schema if it doesn't exist.
When enabled, the system will execute `CREATE SCHEMA IF NOT EXISTS `
before creating metadata tables. This is useful in production environments where
manual schema creation may be restricted.
Default is true.
Note: The PostgreSQL user must have CREATE SCHEMA permission for this to work.
**Only used when backend is `postgres_store`.** |
| `meta_election_lock_id` | Integer | `1` | Advisory lock id in PostgreSQL for election. Effect when using PostgreSQL as kvbackend
Only used when backend is `postgres_store`. |
| `selector` | String | `round_robin` | Datanode selector type.
- `round_robin` (default value)
- `lease_based`
- `load_based`
For details, please see "https://docs.greptime.com/developer-guide/metasrv/selector". |
@@ -445,9 +445,9 @@
| `heartbeat_interval` | String | `3s` | Base heartbeat interval for calculating distributed time constants.
The frontend heartbeat interval is 6 times of the base heartbeat interval.
The flownode/datanode heartbeat interval is 1 times of the base heartbeat interval.
e.g., If the base heartbeat interval is 3s, the frontend heartbeat interval is 18s, the flownode/datanode heartbeat interval is 3s.
Heartbeat intervals are negotiated from metasrv during handshake; local node configs do not override this. |
| `enable_telemetry` | Bool | `true` | Whether to enable greptimedb telemetry. Enabled by default. |
| `runtime` | -- | -- | The runtime options. |
-| `runtime.global_rt_size` | Integer | `8` | The number of threads to execute the runtime for global read operations. |
-| `runtime.compact_rt_size` | Integer | `4` | The number of threads to execute compact operations. |
-| `runtime.compact_rt_max_blocking_threads` | Integer | `4` | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.global_rt_size` | Integer | Auto | The number of threads to execute the runtime for global read operations.
Defaults to max(num_cpus, 2). |
+| `runtime.compact_rt_size` | Integer | Auto | The number of threads to execute compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.compact_rt_max_blocking_threads` | Integer | Auto | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
| `backend_tls` | -- | -- | TLS configuration for kv store backend (applicable for etcd, PostgreSQL, and MySQL backends)
When using etcd, PostgreSQL, or MySQL as metadata store, you can configure TLS here
Note: if TLS is configured in both this section and the `store_addrs` connection string, the
settings here will override the TLS settings in `store_addrs`. |
| `backend_tls.mode` | String | `prefer` | TLS mode, refer to https://www.postgresql.org/docs/current/libpq-ssl.html
- "disable" - No TLS
- "prefer" (default) - Try TLS, fallback to plain
- "require" - Require TLS
- "verify_ca" - Require TLS and verify CA
- "verify_full" - Require TLS and verify hostname |
| `backend_tls.cert_path` | String | `""` | Path to client certificate file (for client authentication)
Like "/path/to/client.crt" |
@@ -459,7 +459,7 @@
| `backend_client.connect_timeout` | String | `3s` | The connect timeout for backend client. |
| `grpc` | -- | -- | The gRPC server options. |
| `grpc.bind_addr` | String | `127.0.0.1:3002` | The address to bind the gRPC server. |
-| `grpc.server_addr` | String | `127.0.0.1:3002` | The communication server address for the frontend and datanode to connect to metasrv.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
+| `grpc.server_addr` | String | Unset | The communication server address for the frontend and datanode to connect to metasrv.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
| `grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
| `grpc.max_recv_message_size` | String | `512MB` | The maximum receive message size for gRPC server. |
| `grpc.max_send_message_size` | String | `512MB` | The maximum send message size for gRPC server. |
@@ -481,7 +481,7 @@
| `datanode` | -- | -- | Datanode options. |
| `datanode.client` | -- | -- | Datanode client options. |
| `datanode.client.timeout` | String | `10s` | Operation timeout. |
-| `datanode.client.connect_timeout` | String | `10s` | Connect server timeout. |
+| `datanode.client.connect_timeout` | String | 1s | Connect server timeout. Defaults to `1s`; this example sets it to `10s`. |
| `datanode.client.tcp_nodelay` | Bool | `true` | `TCP_NODELAY` option for accepted connections. |
| `datanode.client.max_recv_message_size` | String | `512MB` | The maximum receive message size for the gRPC client. |
| `datanode.client.max_send_message_size` | String | `512MB` | The maximum send message size for the gRPC client. |
@@ -503,7 +503,7 @@
| `wal.create_topic_timeout` | String | `30s` | The timeout for creating a Kafka topic.
**It's only used when the provider is `kafka`**. |
| `event_recorder` | -- | -- | Configuration options for the event recorder. |
| `event_recorder.ttl` | String | `90d` | TTL for the events table that will be used to store the events. Default is `90d`. |
-| `event_recorder.event_types` | Array | -- | Event types to record. Current available event types: `region_migration`,
`create_database`, `alter_database`, `drop_database`, `create_flow`,
`drop_flow`, `create_table`, `create_logical_tables`, `alter_table`,
`alter_logical_tables`, `drop_table`, `undrop_table`, `purge_dropped_table`,
`truncate_table`, `create_view`, `drop_view`, `repartition`,
`repartition_group`, `wal_prune`, `batch_gc`, `reconcile_catalog`,
`reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
+| `event_recorder.event_types` | Array | All | Event types to record. Current available event types: `region_migration`,
`create_database`, `alter_database`, `drop_database`, `create_flow`,
`drop_flow`, `create_table`, `create_logical_tables`, `alter_table`,
`alter_logical_tables`, `drop_table`, `undrop_table`, `purge_dropped_table`,
`truncate_table`, `create_view`, `drop_view`, `repartition`,
`repartition_group`, `wal_prune`, `batch_gc`, `reconcile_catalog`,
`reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
When omitted, all current and future event types are recorded.
Set to an empty array to disable event recording. |
| `stats_persistence` | -- | -- | Configuration options for the stats persistence. |
| `stats_persistence.ttl` | String | `0s` | TTL for the stats table that will be used to store the stats.
Set to `0s` to disable stats persistence.
Default is `0s`.
If you want to enable stats persistence, set the TTL to a value greater than 0.
It is recommended to set a small value, e.g., `3h`. |
| `stats_persistence.interval` | String | `10m` | The interval to persist the stats. Default is `10m`.
The minimum value is `10m`, if the value is less than `10m`, it will be overridden to `10m`. |
@@ -548,22 +548,22 @@
| `http.body_limit` | String | `64MB` | HTTP request body limit.
The following units are supported: `B`, `KB`, `KiB`, `MB`, `MiB`, `GB`, `GiB`, `TB`, `TiB`, `PB`, `PiB`.
Set to 0 to disable limit. |
| `grpc` | -- | -- | The gRPC server options. |
| `grpc.bind_addr` | String | `127.0.0.1:3001` | The address to bind the gRPC server. |
-| `grpc.server_addr` | String | `127.0.0.1:3001` | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
+| `grpc.server_addr` | String | Unset | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
| `grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
| `grpc.max_recv_message_size` | String | `512MB` | The maximum receive message size for gRPC server. |
| `grpc.max_send_message_size` | String | `512MB` | The maximum send message size for gRPC server. |
-| `grpc.flight_compression` | String | `arrow_ipc` | Compression mode for datanode side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `none` |
+| `grpc.flight_compression` | String | `arrow_ipc` | Compression mode for datanode side Arrow IPC service. Available options:
- `none`: disable all compression
- `transport`: only enable gRPC transport compression (zstd)
- `arrow_ipc`: only enable Arrow IPC compression (lz4)
- `all`: enable all compression.
Default to `arrow_ipc`. |
| `grpc.tls` | -- | -- | gRPC server TLS options, see `mysql.tls` section. |
| `grpc.tls.mode` | String | `disable` | TLS mode. |
| `grpc.tls.cert_path` | String | Unset | Certificate file path. |
| `grpc.tls.key_path` | String | Unset | Private key file path. |
| `grpc.tls.watch` | Bool | `false` | Watch for Certificate and key file change and auto reload.
For now, gRPC tls config does not support auto reload. |
| `runtime` | -- | -- | The runtime options. |
-| `runtime.global_rt_size` | Integer | `8` | The number of threads to execute the runtime for global read operations. |
-| `runtime.compact_rt_size` | Integer | `4` | The number of threads to execute compact operations. |
-| `runtime.compact_rt_max_blocking_threads` | Integer | `4` | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
-| `runtime.query_rt_size` | Integer | `7` | The number of threads to execute datanode query operations.
Defaults to max(num_cpus - 1, 2). |
-| `runtime.ingest_rt_size` | Integer | `8` | The number of threads to execute datanode ingestion operations. |
+| `runtime.global_rt_size` | Integer | Auto | The number of threads to execute the runtime for global read operations.
Defaults to max(num_cpus, 2). |
+| `runtime.compact_rt_size` | Integer | Auto | The number of threads to execute compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.compact_rt_max_blocking_threads` | Integer | Auto | The maximum number of blocking threads for compact operations.
Defaults to max(num_cpus / 2, 2). |
+| `runtime.query_rt_size` | Integer | Auto | The number of threads to execute datanode query operations.
Defaults to max(num_cpus - 1, 2). |
+| `runtime.ingest_rt_size` | Integer | Auto | The number of threads to execute datanode ingestion operations.
Defaults to max(num_cpus, 2). |
| `runtime.experimental_workload_scheduler` | -- | -- | Experimental weighted, work-conserving query/write task scheduler. |
| `runtime.experimental_workload_scheduler.enable` | Bool | `false` | Enable when concurrent queries and writes interfere with each other—for example, when long-running queries increase ingestion latency.
The weights set their relative runtime shares while both are backlogged. Disabled by default. |
| `runtime.experimental_workload_scheduler.query_weight` | Integer | `2` | Relative query share while both query and write workloads are backlogged. |
@@ -589,7 +589,7 @@
| `wal.enable_log_recycle` | Bool | `true` | Whether to reuse logically truncated log files.
**It's only used when the provider is `raft_engine`**. |
| `wal.prefill_log_files` | Bool | `false` | Whether to pre-create log files on start up.
**It's only used when the provider is `raft_engine`**. |
| `wal.sync_period` | String | `5s` | Duration for fsyncing log files.
**It's only used when the provider is `raft_engine`**. |
-| `wal.recovery_parallelism` | Integer | `2` | Parallelism during WAL recovery. |
+| `wal.recovery_parallelism` | Integer | Auto | Parallelism during WAL recovery. Defaults to the number of CPU cores; this example sets it to 2. |
| `wal.broker_endpoints` | Array | -- | The Kafka broker endpoints.
**It's only used when the provider is `kafka`**. |
| `wal.connect_timeout` | String | `3s` | The connect timeout for kafka client.
**It's only used when the provider is `kafka`**. |
| `wal.timeout` | String | `5s` | The total request timeout for kafka client.
**It's only used when the provider is `kafka`**. |
@@ -607,7 +607,7 @@
| `wal.on_corrupted_segment` | String | `skip` | What a read does with a segment that still does not decode after a second fetch, because its checksum does not match or its content disagrees with its footer entry.
- `skip`: the segment is skipped and recorded as a WAL hole of its region, a metric is incremented and a warning is logged; the other regions of the object are unaffected (the default).
- `fail`: the read fails, so the region does not open.
**It's only used when the provider is `experimental_object_store`**. |
| `query` | -- | -- | The query engine options. |
| `query.parallelism` | Integer | `0` | Parallelism of the query engine.
Default to 0, which means the number of CPU cores. |
-| `query.memory_pool_size` | String | `50%` | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit (unbounded, default behavior).
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
+| `query.memory_pool_size` | String | 0 | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
| `query.experimental_memory_pool_policy` | String | `greedy` | Experimental memory pool allocation policy:
- "greedy" (default): first-come-first-served allocation; preserves current behavior.
- "fair": divides available memory among spillable operators and may spill earlier.
Only effective when `memory_pool_size` is bounded (>0). |
| `query.experimental_spill_mode` | String | `default` | Spill mode:
- "default": preserve DataFusion built-in OS temp directory (default).
- "custom": explicitly configure spill path, quota, and compression.
- "disabled": explicitly disable disk spilling.
Set this to "custom" before using the path/quota/compression keys below. |
| `query.experimental_spill_path` | String | Unset | Spill directory path. Ignored unless mode is "custom". |
@@ -640,7 +640,7 @@
| `storage.http_client.skip_ssl_validation` | Bool | `false` | To skip the ssl verification
**Security Notice**: Setting `skip_ssl_validation = true` disables certificate verification, making connections vulnerable to man-in-the-middle attacks. Only use this in development or trusted private networks. |
| `[[region_engine]]` | -- | -- | The region engine options. You can configure multiple region engines.
Each engine type (mito, file, metric) may appear only once; duplicates cause startup to fail. |
| `region_engine.mito` | -- | -- | The Mito engine options. |
-| `region_engine.mito.num_workers` | Integer | `8` | Number of region workers. |
+| `region_engine.mito.num_workers` | Integer | Auto | Number of region workers. Defaults to half of the available CPU cores, rounded up. |
| `region_engine.mito.worker_channel_size` | Integer | `128` | Request channel size of each worker. |
| `region_engine.mito.worker_request_batch_size` | Integer | `64` | Max batch size for a worker to handle requests. |
| `region_engine.mito.manifest_checkpoint_distance` | Integer | `10` | Number of meta action updated to trigger a new checkpoint for the manifest. |
@@ -757,9 +757,9 @@
| `flow.batching_mode.frontend_tls.client_cert_path` | String | Unset | Client Certificate file path. |
| `flow.batching_mode.frontend_tls.client_key_path` | String | Unset | Client Private key file path. |
| `grpc` | -- | -- | The gRPC server options. |
-| `grpc.bind_addr` | String | `127.0.0.1:6800` | The address to bind the gRPC server. |
-| `grpc.server_addr` | String | `127.0.0.1:6800` | The address advertised to the metasrv,
and used for connections from outside the host |
-| `grpc.runtime_size` | Integer | `2` | The number of server worker threads. |
+| `grpc.bind_addr` | String | 127.0.0.1:3004 | The address to bind the gRPC server. Defaults to `127.0.0.1:3004`; this example sets it to `127.0.0.1:6800`. |
+| `grpc.server_addr` | String | Unset | The address advertised to the metasrv, and used for connections from outside the host.
If left empty or unset, the server will automatically use the IP address of the first network interface
on the host, with the same port number as the one specified in `grpc.bind_addr`. |
+| `grpc.runtime_size` | Integer | 8 | The number of server worker threads. Defaults to 8; this example sets it to 2. |
| `grpc.max_recv_message_size` | String | `512MB` | The maximum receive message size for gRPC server. |
| `grpc.max_send_message_size` | String | `512MB` | The maximum send message size for gRPC server. |
| `http` | -- | -- | The HTTP server options. |
@@ -793,7 +793,7 @@
| `tracing.tokio_console_addr` | String | Unset | The tokio console address. |
| `query` | -- | -- | -- |
| `query.parallelism` | Integer | `1` | Parallelism of the query engine for query sent by flownode.
Default to 1, so it won't use too much cpu or memory |
-| `query.memory_pool_size` | String | `50%` | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "1GB", "2GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit (unbounded, default behavior).
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
+| `query.memory_pool_size` | String | 0 | Memory pool size for query execution operators (aggregation, sorting, join).
Supports absolute size (e.g., "1GB", "2GB") or percentage of system memory (e.g., "20%").
Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
When this limit is reached, queries will fail with ResourceExhausted error.
NOTE: This does NOT limit memory used by table scans. |
| `query.experimental_memory_pool_policy` | String | `greedy` | Experimental memory pool allocation policy:
- "greedy" (default): first-come-first-served allocation; preserves current behavior.
- "fair": divides available memory among spillable operators and may spill earlier.
Only effective when `memory_pool_size` is bounded (>0). |
| `query.experimental_spill_mode` | String | `default` | Spill mode:
- "default": preserve DataFusion built-in OS temp directory (default).
- "custom": explicitly configure spill path, quota, and compression.
- "disabled": explicitly disable disk spilling.
Set this to "custom" before using the path/quota/compression keys below. |
| `query.experimental_spill_path` | String | Unset | Spill directory path. Ignored unless mode is "custom". |
diff --git a/config/datanode.example.toml b/config/datanode.example.toml
index e61ef3fbf22..d0f7da36acd 100644
--- a/config/datanode.example.toml
+++ b/config/datanode.example.toml
@@ -45,6 +45,7 @@ bind_addr = "127.0.0.1:3001"
## The address advertised to the metasrv, and used for connections from outside the host.
## If left empty or unset, the server will automatically use the IP address of the first network interface
## on the host, with the same port number as the one specified in `grpc.bind_addr`.
+## @toml2docs:none-default
server_addr = "127.0.0.1:3001"
## The number of server worker threads.
runtime_size = 8
@@ -57,7 +58,7 @@ max_send_message_size = "512MB"
## - `transport`: only enable gRPC transport compression (zstd)
## - `arrow_ipc`: only enable Arrow IPC compression (lz4)
## - `all`: enable all compression.
-## Default to `none`
+## Default to `arrow_ipc`.
flight_compression = "arrow_ipc"
## gRPC server TLS options, see `mysql.tls` section.
@@ -80,16 +81,24 @@ watch = false
## The runtime options.
#+ [runtime]
## The number of threads to execute the runtime for global read operations.
+## Defaults to max(num_cpus, 2).
+## @toml2docs:none-default="Auto"
#+ global_rt_size = 8
## The number of threads to execute compact operations.
+## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_size = 4
## The maximum number of blocking threads for compact operations.
## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_max_blocking_threads = 4
## The number of threads to execute datanode query operations.
## Defaults to max(num_cpus - 1, 2).
+## @toml2docs:none-default="Auto"
#+ query_rt_size = 7
## The number of threads to execute datanode ingestion operations.
+## Defaults to max(num_cpus, 2).
+## @toml2docs:none-default="Auto"
#+ ingest_rt_size = 8
## Experimental weighted, work-conserving query/write task scheduler.
@@ -176,7 +185,8 @@ prefill_log_files = false
## **It's only used when the provider is `raft_engine`**.
sync_period = "5s"
-## Parallelism during WAL recovery.
+## Parallelism during WAL recovery. Defaults to the number of CPU cores; this example sets it to 2.
+## @toml2docs:none-default="Auto"
recovery_parallelism = 2
## The Kafka broker endpoints.
@@ -330,9 +340,10 @@ parallelism = 0
## Memory pool size for query execution operators (aggregation, sorting, join).
## Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
-## Setting it to 0 disables the limit (unbounded, default behavior).
+## Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
## When this limit is reached, queries will fail with ResourceExhausted error.
## NOTE: This does NOT limit memory used by table scans.
+## @toml2docs:none-default="0"
memory_pool_size = "50%"
## Experimental memory pool allocation policy:
@@ -503,7 +514,8 @@ skip_ssl_validation = false
## The Mito engine options.
[region_engine.mito]
-## Number of region workers.
+## Number of region workers. Defaults to half of the available CPU cores, rounded up.
+## @toml2docs:none-default="Auto"
#+ num_workers = 8
## Request channel size of each worker.
diff --git a/config/flownode.example.toml b/config/flownode.example.toml
index b0a53bee54a..fab31fed510 100644
--- a/config/flownode.example.toml
+++ b/config/flownode.example.toml
@@ -44,12 +44,16 @@ node_id = 14
## The gRPC server options.
[grpc]
-## The address to bind the gRPC server.
+## The address to bind the gRPC server. Defaults to `127.0.0.1:3004`; this example sets it to `127.0.0.1:6800`.
+## @toml2docs:none-default="127.0.0.1:3004"
bind_addr = "127.0.0.1:6800"
-## The address advertised to the metasrv,
-## and used for connections from outside the host
+## The address advertised to the metasrv, and used for connections from outside the host.
+## If left empty or unset, the server will automatically use the IP address of the first network interface
+## on the host, with the same port number as the one specified in `grpc.bind_addr`.
+## @toml2docs:none-default
server_addr = "127.0.0.1:6800"
-## The number of server worker threads.
+## The number of server worker threads. Defaults to 8; this example sets it to 2.
+## @toml2docs:none-default="8"
runtime_size = 2
## The maximum receive message size for gRPC server.
max_recv_message_size = "512MB"
@@ -153,9 +157,10 @@ parallelism = 1
## Memory pool size for query execution operators (aggregation, sorting, join).
## Supports absolute size (e.g., "1GB", "2GB") or percentage of system memory (e.g., "20%").
-## Setting it to 0 disables the limit (unbounded, default behavior).
+## Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
## When this limit is reached, queries will fail with ResourceExhausted error.
## NOTE: This does NOT limit memory used by table scans.
+## @toml2docs:none-default="0"
memory_pool_size = "50%"
## Experimental memory pool allocation policy:
diff --git a/config/frontend.example.toml b/config/frontend.example.toml
index b528da0304f..65ac54d5d33 100644
--- a/config/frontend.example.toml
+++ b/config/frontend.example.toml
@@ -20,8 +20,8 @@ default_column_prefix = "greptime"
## Password verifier formats: "plain:", "pbkdf2_sha256:::",
## "mysql_native_password:",
## "pg_scram_sha256::::"
-## "pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but cannot authenticate over MySQL's
-## native password handshake; a MySQL client must send the password in cleartext for such users.
+## "pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but such users cannot log in over MySQL:
+## `static_user_provider` and `watch_file_user_provider` only negotiate `mysql_native_password`, which cannot verify these formats.
## "mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
## PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
## "mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
@@ -33,22 +33,26 @@ default_column_prefix = "greptime"
## Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
## Set to 0 to disable the limit. Default: "0" (unlimited)
-## @toml2docs:none-default
+## @toml2docs:none-default="0"
#+ max_in_flight_write_bytes = "1GB"
## Policy when write bytes quota is exhausted.
## Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail"
-## @toml2docs:none-default
#+ write_bytes_exhausted_policy = "wait"
## The runtime options.
#+ [runtime]
## The number of threads to execute the runtime for global read operations.
+## Defaults to max(num_cpus, 2).
+## @toml2docs:none-default="Auto"
#+ global_rt_size = 8
## The number of threads to execute compact operations.
+## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_size = 4
## The maximum number of blocking threads for compact operations.
## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_max_blocking_threads = 4
## The HTTP server options.
@@ -86,6 +90,7 @@ bind_addr = "127.0.0.1:4001"
## The address advertised to the metasrv, and used for connections from outside the host.
## If left empty or unset, the server will automatically use the IP address of the first network interface
## on the host, with the same port number as the one specified in `grpc.bind_addr`.
+## @toml2docs:none-default
server_addr = "127.0.0.1:4001"
## The number of server worker threads.
runtime_size = 8
@@ -94,7 +99,7 @@ runtime_size = 8
## - `transport`: only enable gRPC transport compression (zstd)
## - `arrow_ipc`: only enable Arrow IPC compression (lz4)
## - `all`: enable all compression.
-## Default to `none`
+## Default to `arrow_ipc`.
flight_compression = "arrow_ipc"
## The maximum connection age for gRPC connection.
## The value can be a human-readable time string. For example: `10m` for ten minutes or `1h` for one hour.
@@ -120,12 +125,15 @@ key_path = ""
watch = false
## The internal gRPC server options. Internal gRPC port for nodes inside cluster to access frontend.
+## The internal gRPC server starts only when this section is set.
[internal_grpc]
## The address to bind the gRPC server.
+## If unset, it falls back to `127.0.0.1:4001`, the same address as `grpc.bind_addr`.
+## @toml2docs:none-default
bind_addr = "127.0.0.1:4010"
## The address advertised to the metasrv, and used for connections from outside the host.
-## If left empty or unset, the server will automatically use the IP address of the first network interface
-## on the host, with the same port number as the one specified in `internal_grpc.bind_addr`.
+## Unlike `grpc.server_addr`, it is not detected automatically; set it explicitly.
+## @toml2docs:none-default
server_addr = "127.0.0.1:4010"
## The number of server worker threads.
runtime_size = 8
@@ -134,7 +142,7 @@ runtime_size = 8
## - `transport`: only enable gRPC transport compression (zstd)
## - `arrow_ipc`: only enable Arrow IPC compression (lz4)
## - `all`: enable all compression.
-## Default to `none`
+## Default to `arrow_ipc`.
flight_compression = "arrow_ipc"
## internal gRPC server TLS options, see `mysql.tls` section.
@@ -352,9 +360,10 @@ allow_query_fallback = false
## Memory pool size for query execution operators (aggregation, sorting, join).
## Supports absolute size (e.g., "4GB", "8GB") or percentage of system memory (e.g., "30%").
-## Setting it to 0 disables the limit (unbounded, default behavior).
+## Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
## When this limit is reached, queries will fail with ResourceExhausted error.
## NOTE: This does NOT limit memory used by table scans (only applies to datanodes).
+## @toml2docs:none-default="0"
memory_pool_size = "50%"
## Experimental memory pool allocation policy:
@@ -385,6 +394,8 @@ memory_pool_size = "50%"
[datanode]
## Datanode client options.
[datanode.client]
+## Connect server timeout. Defaults to `1s`; this example sets it to `10s`.
+## @toml2docs:none-default="1s"
connect_timeout = "10s"
tcp_nodelay = true
## The maximum receive message size for the gRPC client.
@@ -489,4 +500,5 @@ ttl = "90d"
## Event types to record. Current available event type: `admin_function`.
## When omitted, all current and future event types are recorded.
## Set to an empty array to disable event recording.
+## @toml2docs:none-default="All"
#+ event_types = ["admin_function"]
diff --git a/config/metasrv.example.toml b/config/metasrv.example.toml
index b923c5a549c..fe4c38d02f9 100644
--- a/config/metasrv.example.toml
+++ b/config/metasrv.example.toml
@@ -35,6 +35,8 @@ meta_table_name = "greptime_metakv"
## When PostgreSQL public schema is not writable (e.g., PostgreSQL 15+ with restricted public),
## set this to a writable schema. GreptimeDB will use `meta_schema_name`.`meta_table_name`.
## **Only used when backend is `postgres_store`.**
+## Unset by default; this example sets it to `greptime_schema`.
+## @toml2docs:none-default
meta_schema_name = "greptime_schema"
## Automatically create PostgreSQL schema if it doesn't exist.
@@ -88,11 +90,16 @@ node_max_idle_time = "24hours"
## The runtime options.
#+ [runtime]
## The number of threads to execute the runtime for global read operations.
+## Defaults to max(num_cpus, 2).
+## @toml2docs:none-default="Auto"
#+ global_rt_size = 8
## The number of threads to execute compact operations.
+## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_size = 4
## The maximum number of blocking threads for compact operations.
## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_max_blocking_threads = 4
## TLS configuration for kv store backend (applicable for etcd, PostgreSQL, and MySQL backends)
@@ -140,6 +147,7 @@ bind_addr = "127.0.0.1:3002"
## The communication server address for the frontend and datanode to connect to metasrv.
## If left empty or unset, the server will automatically use the IP address of the first network interface
## on the host, with the same port number as the one specified in `grpc.bind_addr`.
+## @toml2docs:none-default
server_addr = "127.0.0.1:3002"
## The number of server worker threads.
runtime_size = 8
@@ -206,7 +214,8 @@ acceptable_heartbeat_pause = "10000ms"
## Operation timeout.
timeout = "10s"
-## Connect server timeout.
+## Connect server timeout. Defaults to `1s`; this example sets it to `10s`.
+## @toml2docs:none-default="1s"
connect_timeout = "10s"
## `TCP_NODELAY` option for accepted connections.
@@ -332,6 +341,7 @@ ttl = "90d"
## `reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
## When omitted, all current and future event types are recorded.
## Set to an empty array to disable event recording.
+## @toml2docs:none-default="All"
#+ event_types = ["region_migration"]
## Configuration options for the stats persistence.
diff --git a/config/standalone.example.toml b/config/standalone.example.toml
index 417a3da6220..cebbf8ac265 100644
--- a/config/standalone.example.toml
+++ b/config/standalone.example.toml
@@ -20,8 +20,8 @@ default_column_prefix = "greptime"
## Password verifier formats: "plain:", "pbkdf2_sha256:::",
## "mysql_native_password:",
## "pg_scram_sha256::::"
-## "pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but cannot authenticate over MySQL's
-## native password handshake; a MySQL client must send the password in cleartext for such users.
+## "pbkdf2_sha256" and "pg_scram_sha256" protect passwords at rest, but such users cannot log in over MySQL:
+## `static_user_provider` and `watch_file_user_provider` only negotiate `mysql_native_password`, which cannot verify these formats.
## "mysql_native_password" is MySQL-specific and cannot authenticate over PostgreSQL at all.
## PostgreSQL SCRAM only covers "plain" and "pg_scram_sha256" users; if any user is "pbkdf2_sha256" or
## "mysql_native_password", PostgreSQL falls back to cleartext password auth for every user.
@@ -33,12 +33,11 @@ default_column_prefix = "greptime"
## Maximum total memory for all concurrent write request bodies and messages (HTTP, gRPC, Flight).
## Set to 0 to disable the limit. Default: "0" (unlimited)
-## @toml2docs:none-default
+## @toml2docs:none-default="0"
#+ max_in_flight_write_bytes = "1GB"
## Policy when write bytes quota is exhausted.
## Options: "wait" (default, 10s timeout), "wait()" (e.g., "wait(30s)"), "fail"
-## @toml2docs:none-default
#+ write_bytes_exhausted_policy = "wait"
## Initialize all regions in the background during the startup.
@@ -48,20 +47,22 @@ init_regions_in_background = false
## Parallelism of initializing regions.
init_regions_parallelism = 16
-## The maximum concurrent queries allowed to be executed. Zero means unlimited.
-max_concurrent_queries = 0
-
## Enable telemetry to collect anonymous usage data. Enabled by default.
#+ enable_telemetry = true
## The runtime options.
#+ [runtime]
## The number of threads to execute the runtime for global read operations.
+## Defaults to max(num_cpus, 2).
+## @toml2docs:none-default="Auto"
#+ global_rt_size = 8
## The number of threads to execute compact operations.
+## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_size = 4
## The maximum number of blocking threads for compact operations.
## Defaults to max(num_cpus / 2, 2).
+## @toml2docs:none-default="Auto"
#+ compact_rt_max_blocking_threads = 4
## Experimental weighted, work-conserving query/write task scheduler.
@@ -339,7 +340,8 @@ prefill_log_files = false
## **It's only used when the provider is `raft_engine`**.
sync_period = "5s"
-## Parallelism during WAL recovery.
+## Parallelism during WAL recovery. Defaults to the number of CPU cores; this example sets it to 2.
+## @toml2docs:none-default="Auto"
recovery_parallelism = 2
## The Kafka broker endpoints.
@@ -533,9 +535,10 @@ parallelism = 0
## Memory pool size for query execution operators (aggregation, sorting, join).
## Supports absolute size (e.g., "2GB", "4GB") or percentage of system memory (e.g., "20%").
-## Setting it to 0 disables the limit (unbounded, default behavior).
+## Setting it to 0 disables the limit. Defaults to 0 (unlimited); this example sets it to `50%`.
## When this limit is reached, queries will fail with ResourceExhausted error.
## NOTE: This does NOT limit memory used by table scans.
+## @toml2docs:none-default="0"
memory_pool_size = "50%"
## Experimental memory pool allocation policy:
@@ -715,7 +718,8 @@ skip_ssl_validation = false
## The Mito engine options.
[region_engine.mito]
-## Number of region workers.
+## Number of region workers. Defaults to half of the available CPU cores, rounded up.
+## @toml2docs:none-default="Auto"
#+ num_workers = 8
## Request channel size of each worker.
@@ -1057,19 +1061,21 @@ default_ratio = 1.0
## The slow query log options.
[slow_query]
## Whether to enable slow query log.
-#+ enable = false
+enable = true
## The record type of slow queries. It can be `system_table` or `log`.
-## @toml2docs:none-default
-#+ record_type = "system_table"
+## If `system_table` is selected, the slow queries will be recorded in a system table `greptime_private.slow_queries`.
+## If `log` is selected, the slow queries will be logged in a log file `greptimedb-slow-queries.*`.
+record_type = "system_table"
-## The threshold of slow query.
-## @toml2docs:none-default
-#+ threshold = "10s"
+## The threshold of slow query. It can be human readable time string, for example: `10s`, `100ms`, `1s`.
+threshold = "30s"
-## The sampling ratio of slow query log. The value should be in the range of (0, 1].
-## @toml2docs:none-default
-#+ sample_ratio = 1.0
+## The sampling ratio of slow query log. The value should be in the range of (0, 1]. For example, `0.1` means 10% of the slow queries will be logged and `1.0` means all slow queries will be logged.
+sample_ratio = 1.0
+
+## The TTL of the `slow_queries` system table. Default is `90d` when `record_type` is `system_table`.
+ttl = "90d"
## The tracing options. Only effect when compiled with `tokio-console` feature.
#+ [tracing]
@@ -1094,6 +1100,7 @@ ttl = "90d"
## `reconcile_database`, `reconcile_table`, `reconcile_logical_tables`.
## When omitted, all current and future event types are recorded.
## Set to an empty array to disable event recording.
+## @toml2docs:none-default="All"
#+ event_types = ["create_database"]
## The memory options.
diff --git a/src/cmd/tests/load_config_test.rs b/src/cmd/tests/load_config_test.rs
index cc095c5c92e..ba38793b8cd 100644
--- a/src/cmd/tests/load_config_test.rs
+++ b/src/cmd/tests/load_config_test.rs
@@ -475,6 +475,261 @@ fn test_load_standalone_example_config() {
similar_asserts::assert_eq!(options, expected);
}
+/// Renders an example config with its `#+` options enabled, as `config.md`
+/// lists them. With `drop_none_default`, options annotated with
+/// `@toml2docs:none-default` are removed, because `config.md` does not present
+/// their example value as the default.
+fn render_example(example: &str, drop_none_default: bool) -> String {
+ let mut rendered = String::new();
+ let mut none_default = false;
+ for line in example.lines() {
+ let line = line.trim_start();
+ if line.starts_with("##") {
+ none_default |= line.contains("@toml2docs:none-default");
+ continue;
+ }
+ let line = line.strip_prefix("#+").map_or(line, str::trim_start);
+ let is_option = !line.starts_with('[') && line.contains('=');
+ if !(is_option && drop_none_default && none_default) {
+ rendered.push_str(line);
+ rendered.push('\n');
+ }
+ none_default = false;
+ }
+ rendered
+}
+
+/// Flattens leaf values into dotted paths. Arrays of tables such as
+/// `region_engine` are merged, since each element is keyed by its engine name.
+fn leaf_values(value: &toml::Value, prefix: &str, leaves: &mut Vec<(String, toml::Value)>) {
+ match value {
+ toml::Value::Table(table) => {
+ for (key, value) in table {
+ let path = if prefix.is_empty() {
+ key.clone()
+ } else {
+ format!("{prefix}.{key}")
+ };
+ leaf_values(value, &path, leaves);
+ }
+ }
+ toml::Value::Array(array)
+ if array.iter().all(toml::Value::is_table) && !array.is_empty() =>
+ {
+ for element in array {
+ leaf_values(element, prefix, leaves);
+ }
+ }
+ _ => leaves.push((prefix.to_string(), value.clone())),
+ }
+}
+
+/// Removes the option at a dotted path produced by [`leaf_values`].
+fn remove_leaf(value: &mut toml::Value, path: &str) -> bool {
+ match value {
+ toml::Value::Array(array) => array.iter_mut().any(|element| remove_leaf(element, path)),
+ toml::Value::Table(table) => match path.split_once('.') {
+ None => table.remove(path).is_some(),
+ Some((head, rest)) => table
+ .get_mut(head)
+ .is_some_and(|value| remove_leaf(value, rest)),
+ },
+ _ => false,
+ }
+}
+
+fn load_as_leaves(
+ config: Option<&str>,
+) -> common_config::error::Result>
+where
+ T: Configurable + serde::Serialize,
+{
+ let file = config.map(|config| {
+ let mut file = create_named_temp_file();
+ file.write_all(config.as_bytes()).unwrap();
+ file
+ });
+ let options = GreptimeOptions::::load_layered_options(
+ file.as_ref().map(|file| file.path().to_str().unwrap()),
+ "",
+ )?;
+ let mut leaves = Vec::new();
+ leaf_values(&toml::Value::try_from(&options).unwrap(), "", &mut leaves);
+ Ok(leaves.into_iter().collect())
+}
+
+/// Returns the default of an option inside the example's other settings, so
+/// that options in sections absent by default still have one to compare with.
+/// Removes the closest enclosing table that still loads without the option.
+fn default_within_example(full: &toml::Value, path: &str) -> Option
+where
+ T: Configurable + serde::Serialize,
+{
+ let mut removed = path;
+ loop {
+ let mut without = full.clone();
+ assert!(remove_leaf(&mut without, removed));
+ if let Ok(defaults) = load_as_leaves::(Some(&toml::to_string(&without).unwrap())) {
+ return defaults.get(path).cloned();
+ }
+ removed = removed
+ .rsplit_once('.')
+ .unwrap_or_else(|| panic!("the example does not load without `{path}`"))
+ .0;
+ }
+}
+
+/// Checks that every option in an example config exists, and that every value
+/// `config.md` presents as a default is the actual default.
+///
+/// `variants` lists tagged sections, e.g. `("wal", "provider", ["kafka"])`,
+/// whose options only deserialize under a specific tag value.
+fn check_example_defaults(name: &str, variants: &[(&str, &str, &[&str])]) -> Vec
+where
+ T: Configurable + serde::Serialize,
+{
+ let example = std::fs::read_to_string(common_test_util::find_workspace_path(&format!(
+ "config/{name}"
+ )))
+ .unwrap();
+ let full: toml::Value = toml::from_str(&render_example(&example, false)).unwrap();
+ let documented: toml::Value = toml::from_str(&render_example(&example, true)).unwrap();
+
+ // (options loaded from the example, options loaded without config) per variant
+ let mut loaded = vec![(
+ load_as_leaves::(Some(&toml::to_string(&full).unwrap())).unwrap(),
+ load_as_leaves::(None).unwrap(),
+ )];
+ for (section, tag, values) in variants {
+ for value in *values {
+ let mut variant = full.clone();
+ variant[section][tag] = toml::Value::String(value.to_string());
+ loaded.push((
+ load_as_leaves::(Some(&toml::to_string(&variant).unwrap())).unwrap(),
+ load_as_leaves::(Some(&format!("[{section}]\n{tag} = \"{value}\"\n"))).unwrap(),
+ ));
+ }
+ }
+
+ // Deserialize-only fields, invisible in the serialized options.
+ const SKIP_SERIALIZING: &[&str] = &[
+ "storage.access_key_id",
+ "storage.secret_access_key",
+ "storage.access_key_secret",
+ "storage.account_name",
+ "storage.account_key",
+ "storage.credential_path",
+ "storage.credential",
+ "region_engine.mito.inverted_index.intermediate_path",
+ ];
+
+ let mut errors = Vec::new();
+ let mut full_leaves = Vec::new();
+ leaf_values(&full, "", &mut full_leaves);
+ for (path, _) in full_leaves {
+ if SKIP_SERIALIZING.contains(&path.as_str())
+ || (path == "tracing.tokio_console_addr" && !cfg!(feature = "tokio-console"))
+ {
+ continue;
+ }
+ if !loaded
+ .iter()
+ .any(|(example, _)| example.contains_key(&path))
+ {
+ errors.push(format!("{name}: `{path}` is not a known option"));
+ }
+ }
+
+ // Options left unset by default and resolved where they are used.
+ let resolved_at_runtime: [(&str, toml::Value); 7] = [
+ (
+ "logging.dir",
+ format!("{DEFAULT_DATA_HOME}/{DEFAULT_LOGGING_DIR}").into(),
+ ),
+ ("logging.otlp_endpoint", DEFAULT_OTLP_HTTP_ENDPOINT.into()),
+ ("logging.otlp_export_protocol", "http".into()),
+ ("logging.tracing_sample_ratio.default_ratio", 1.0.into()),
+ ("wal.sync_period", "5s".into()),
+ (
+ "storage.copy_root",
+ format!("{DEFAULT_DATA_HOME}/copy").into(),
+ ),
+ ("flow.batching_mode.frontend_tls.enabled", false.into()),
+ ];
+
+ let mut documented_leaves = Vec::new();
+ leaf_values(&documented, "", &mut documented_leaves);
+ for (path, documented_value) in documented_leaves {
+ if SKIP_SERIALIZING.contains(&path.as_str()) {
+ continue;
+ }
+ if let Some((_, resolved)) = resolved_at_runtime.iter().find(|(p, _)| *p == path) {
+ if &documented_value != resolved {
+ errors.push(format!(
+ "{name}: `{path}` is documented as default `{documented_value}`, but resolves to `{resolved}`"
+ ));
+ }
+ continue;
+ }
+ let mut pairs = loaded
+ .iter()
+ .filter_map(|(example, default)| Some((example.get(&path)?, default.get(&path)?)))
+ .map(|(example, default)| (example.clone(), default.clone()))
+ .collect::>();
+ if pairs.is_empty() {
+ // The option sits in a section that is absent without config, or
+ // is itself optional.
+ match default_within_example::(&full, &path) {
+ Some(default) => pairs.push((loaded[0].0[&path].clone(), default)),
+ None => {
+ errors.push(format!(
+ "{name}: `{path}` has no default to compare with; annotate it with \
+ `@toml2docs:none-default` or list its runtime default in this test"
+ ));
+ continue;
+ }
+ }
+ }
+ if pairs.iter().all(|(example, default)| example != default) {
+ let (example, default) = &pairs[0];
+ errors.push(format!(
+ "{name}: `{path}` is documented as default `{example}`, but the default is `{default}`; \
+ fix the value or annotate it with `@toml2docs:none-default`"
+ ));
+ }
+ }
+ errors
+}
+
+// The examples document HDFS storage options.
+#[cfg(feature = "hdfs-object-store")]
+#[test]
+fn test_example_configs_document_actual_defaults() {
+ const WAL: (&str, &str, &[&str]) = ("wal", "provider", &["kafka", "experimental_object_store"]);
+ const STORAGE: (&str, &str, &[&str]) =
+ ("storage", "type", &["S3", "Oss", "Azblob", "Gcs", "Hdfs"]);
+
+ let mut errors =
+ check_example_defaults::("standalone.example.toml", &[WAL, STORAGE]);
+ errors.extend(check_example_defaults::(
+ "frontend.example.toml",
+ &[],
+ ));
+ errors.extend(check_example_defaults::(
+ "datanode.example.toml",
+ &[WAL, STORAGE],
+ ));
+ errors.extend(check_example_defaults::(
+ "metasrv.example.toml",
+ &[("wal", "provider", &["kafka"])],
+ ));
+ errors.extend(check_example_defaults::(
+ "flownode.example.toml",
+ &[],
+ ));
+ assert!(errors.is_empty(), "{}", errors.join("\n"));
+}
+
#[test]
fn test_load_removed_histogram_options() {
for enabled in [false, true] {