Documenting features controlled by feature flags
Documenting experimental functionality controlled by feature flags requires a conditional warning on every page describing it. The warning explains the risks and remains visible while the relevant flag is disabled by default in the YDB version whose documentation is being built.
A disabled flag does not necessarily identify an experimental feature. If a flag controls a stable capability that only some users need, document it as an ordinary setting. Confirm the experimental status and the connection between the capability and its flag with the feature owner.
Add a warning
Place the warning at the beginning of the page or section describing the experimental feature. If the feature appears on several pages, add the warning to each one. Documentation changes for experimental functionality are incomplete without this warning.
For a flag in NKikimrConfig.TFeatureFlags, use this snippet:
{% if feature_flags.enable_xxx == false %}
{% note warning "Experimental feature" %}
This feature is under development and is disabled by default by the [`enable_xxx`](../../reference/configuration/feature_flags.md) flag. Its behavior may change without backward compatibility, and the feature may never become generally available. Enabling the flag may cause errors, cluster instability, or make it impossible to change the YDB version. Do not enable this flag in production clusters. [Learn more](../../reference/configuration/feature_flags.md#experimental).
{% endnote %}
{% endif %}
Replace enable_xxx with the actual flag's snake_case name in both the condition and the warning text. Adjust the relative links: the example paths are relative to this article. Use the same flag in the Russian page and the corresponding warning text:
{% if feature_flags.enable_xxx == false %}
{% note warning "Экспериментальная функциональность" %}
Функциональность находится в разработке и по умолчанию выключена флагом [`enable_xxx`](../../reference/configuration/feature_flags.md). Её поведение может измениться без сохранения обратной совместимости, а сама функциональность может так и не стать общедоступной. Включение флага может привести к ошибкам, нестабильной работе кластера или невозможности сменить версию YDB. Не включайте флаг в production-кластерах. [Подробнее](../../reference/configuration/feature_flags.md#experimental).
{% endnote %}
{% endif %}
If availability depends on several flags, make the condition match the implementation's guards. Do not choose a flag solely because its name resembles the feature name.
Choose the variable
Flags are defined in more than ydb/core/protos/feature_flags.proto. For other sources, the variable includes the type name so that identically named fields from different messages remain distinct.
| Source | Example variable |
|---|---|
NKikimrConfig.TFeatureFlags |
feature_flags.enable_xxx |
NKikimrConfig.TTableServiceConfig |
proto_flags.NKikimrConfig.TTableServiceConfig.enable_stream_write |
| Nested protobuf messages | proto_flags.<package>.<message>.<nested_message>.<snake_case_field> |
| Registered C++ structs | compile_time_flags.NActors.NFeatures.TCommonFeatureFlags.probe_spin_cycles |
Package and type names keep their original case; field names use snake_case. For example, EnableStreamWrite becomes enable_stream_write. C++ namespace components are separated by dots in documentation variables.
For a service-config flag, replace the snippet's condition with one using the appropriate protobuf type. For example:
{% if proto_flags.NKikimrConfig.TTableServiceConfig.enable_stream_write == false %}
<!-- Place the warning for the corresponding experimental feature here. -->
{% endif %}
The generator covers registered protobuf sources and their imports, including service configuration, PQ, Blob Storage, authentication, FQ, NBS, and other messages. The registry is ydb/docs/tools/feature_flags/sources.json. Register a source if it is neither listed nor included through imports. For a new C++ source, also check the GitHub workflow build-trigger filters.
A field in the generated inventory does not necessarily control an experimental cluster feature:
Ydb.FeatureFlag.Statusrepresents a public API parameter's state.STATUS_UNSPECIFIEDis not equivalent tofalse.- Viewer fields describe an API response, and physical-query fields describe query-plan data. Their protobuf defaults do not determine feature availability on a cluster.
- Only literal
constexpr boolvalues are read for C++ flags. Computed expressions becomenull: the generator does not execute C++ or determine the configuration of a particular binary build.
For these sources, establish the value's meaning and its connection to the user-facing capability first. Do not apply the boolean condition automatically.
How builds work
Before Diplodoc runs, the generator reads source code from the same checkout as the documentation and adds defaults to the default preset in ydb/docs/presets.yaml. Consequently, main documentation uses values from main, while stable-version documentation uses the corresponding stable branch.
| Variable value | Result of == false |
|---|---|
false |
The warning is visible. |
true |
The warning is hidden. |
null, including a registered deleted flag |
The warning is hidden. |
| Unknown flag or type name | Reference validation fails the build. |
The absence of a warning does not itself prove that a feature is ready: null can also mean an unresolved value. Check the feature's implementation and documentation to establish its status.
The generator reads defaults from protobuf schemas and supported C++ literals. These values do not replace checking a running cluster's configuration and do not include defaults assigned separately by application code.
Do not edit or commit the generated block in presets.yaml. When backporting documentation, carry the snippet with the correct flag name; values are generated from the target branch's source code.
Validate the change
From the repository root, install the dependencies and run the generator:
python3 -m pip install -r ydb/docs/tools/feature_flags/requirements.txt
python3 ydb/docs/tools/feature_flags/generate.py --catalog feature-flag-defaults.json
The generator validates flag names in conditions and creates feature-flag-defaults.json with source paths, types, and values. CI exposes this inventory as the feature-flag-defaults artifact.
Check both PR previews. Confirm that the Russian and English pages use the same flag and condition, that the warning matches the experimental status, and that links point to the reference article and its #experimental section. For local builds, follow the instructions in ydb/docs/README.md.
When a flag is removed
When removing a protobuf field, reserve its original name with reserved. The generator assigns null to the corresponding variable, so a warning guarded by == false is no longer displayed.
If the name cannot be retained in protobuf, such as when an entire message or a C++ field is removed, add the reference to retired_references in sources.json. The entry identifies the variable namespace, original type, and snake_case field name. For example, for a removed service-config field:
{
"namespace": "proto_flags",
"message": "NKikimrConfig.TTableServiceConfig",
"field": "enable_removed_example"
}
A feature_flags entry does not need a type name. For compile_time_flags, use the fully qualified C++ struct name with :: separators. Active fields cannot be marked retired. Do not use the registry to bypass a spelling error: unknown references must be caught during the build.
After removing a flag, check that the feature description remains accurate. Remove obsolete snippets during the next page update. If the feature is still experimental, use its current flag in the condition or keep an unconditional warning.