# CREATE RESOURCE POOL CLASSIFIER
CREATE RESOURCE POOL CLASSIFIER creates a resource pool classifier.
Syntax
CREATE RESOURCE POOL CLASSIFIER <name>
WITH ( <parameter_name> [= <parameter_value>] [, ... ] )
nameтАФ the name of the resource pool classifier being created. It must be unique. The name must not contain characters prohibited for schema objects.WITH ( <parameter_name> [= <parameter_value>] [, ... ] )тАФ allows you to set parameter values that define the behavior of the resource pool classifier.
Common parameters
RANK(Int64) тАФ an optional field that specifies the selection order of the resource pool classifier. If the value is not specified, the maximum existingRANKis taken and 1000 is added to it. Valid values: a unique number in the range .RESOURCE_POOL(String) тАФ the name of the resource pool to which requests matching the classifier's predicates are directed.ACTION(Enum) тАФ the action applied to a request when the classifier matches. Allowed value тАФreject: the request is rejected, and the user receives an error of the formRequest is rejected by classifier '<name>' (rank=<rank>).
Note
The RESOURCE_POOL and ACTION parameters are mutually exclusive: exactly one of them must be specified in a classifier.
Predicate parameters
A predicate is a condition checked for an incoming request. A classifier matches if all of its predicates are satisfied (logical AND). To express OR logic, create multiple classifiers with different RANK values. Classifiers are processed in ascending order of RANK; processing stops at the first match тАФ the request has that classifier's ACTION applied or is directed to its RESOURCE_POOL.
Predicate parameters are optional. A classifier without any predicates matches any request тАФ this is useful for a "catch-all" classifier with the maximum RANK, for example, to direct all unclassified traffic to a specific pool (RESOURCE_POOL) or to reject it (ACTION='reject').
Warning
Be careful when creating a "catch-all" classifier: all classifiers following it by RANK will never fire тАФ processing stops at the first match, and the "catch-all" always matches.
List of predicates:
MEMBER_NAME(String) тАФ the SID of the user or group on whose behalf the request was made. See below for details.HAS_PATH(String) тАФ path to a YDB object accessed by the request; supports wildcards*and?. See below for details.HAS_APP_NAME(String) тАФ client application identifier. See below for details.HAS_FULL_SCAN(String) тАФ path to an object for which a full scan is expected; supports wildcards*and?. See below for details.HAS_STREAM(Bool) тАФ indicates whether the request is streaming. See below for details.
MEMBER_NAME
MEMBER_NAME is compared character by character with the user's SID or any group SID from their authentication token. The SID format depends on how the user logged into the system.
- Built-in YDB users (login/password) тАФ the SID matches the username, without a suffix. For example,
user1. For more information, see Authenticating by username and password. - Cloud users (Access Service) тАФ the SID has the form
<subject_id>@as, where<subject_id>is the user ID in IAM. The suffix is set by theaccess_service_domainparameter (defaultas). For example,ajeb89hv69nujke769fa@as. For more information, see Authentication through a third-party IAM provider. - LDAP тАФ the SID has the form
<login>@<domain>, where the domain is set by theldap_authentication_domainparameter (defaultldap). For example,user1@ldap. For more information, see LDAP directory integration. - External identity providers (OIDC) тАФ the SID has the form
<login>@<domain>, where the domain is set by theexternal_idp_authentication_domainparameter in the authentication configuration (defaultsso). For example,user1@sso.
You can specify either the SID of a specific user or the SID of a group. The all-users@well-known group is automatically added to all authenticated users тАФ it is convenient when you need to direct queries from all authenticated clients to a pool.
Example. Direct requests from user user1@ldap to the olap pool:
CREATE RESOURCE POOL CLASSIFIER cl_user WITH (
RANK=100,
RESOURCE_POOL='olap',
MEMBER_NAME='user1@ldap'
);
HAS_PATH
HAS_PATH compares the paths of YDB objects accessed by the request against the specified mask. The mask supports wildcards: * тАФ any sequence of characters, ? тАФ any single character. The predicate matches if at least one object in the request plan matches the mask.
Example. Direct requests to archive tables to the pool_archive pool:
CREATE RESOURCE POOL CLASSIFIER cl_archive WITH (
RANK=700,
RESOURCE_POOL='pool_archive',
HAS_PATH='/Root/db/archive/*'
);
HAS_APP_NAME
HAS_APP_NAME compares the value against the client application identifier. The value is passed by the client in gRPC request metadata via the x-ydb-application-name header; YDB SDKs provide a way to set it on the client side. Comparison is exact match (no wildcards).
Warning
The HAS_APP_NAME value is set by the client and is not authenticated by the server тАФ do not use it as an access control mechanism. For effective isolation, combine it with MEMBER_NAME or direct unrecognized requests to a sandbox pool with strict limits.
Setting the application identifier on the client:
- YDB UI — fixed value
ydb-ui, set by the viewer and not user-configurable. - YDB CLI — not supported: the client application identifier is not sent in requests.
- YDB C++ SDK — per request via the
Headerparameter ofTRequestSettings:settings.Header({{ NYdb::YDB_APPLICATION_NAME, "my-app" }}), where theYDB_APPLICATION_NAMEconstant equalsx-ydb-application-name. - YDB Go SDK — at the driver level via the
WithApplicationNameoption in theydb.Opencall. - YDB Java SDK — at the transport level via the
GrpcTransportBuilder.withApplicationNamemethod. - YDB Python SDK — no dedicated parameter; the value is set per request via a generic header:
settings.with_header("x-ydb-application-name", "my-app")(theBaseRequestSettings.with_headermethod).
Example. Direct requests from YDB UI to the pool_adhoc pool:
CREATE RESOURCE POOL CLASSIFIER cl_adhoc_ui WITH (
RANK=200,
RESOURCE_POOL='pool_adhoc',
HAS_APP_NAME='ydb-ui'
);
HAS_FULL_SCAN
HAS_FULL_SCAN identifies requests that contain a full scan of the specified objects. A full scan is a table read without a key or key-range constraint. The argument is a path mask supporting wildcards * and ?; the predicate matches if there is at least one such object in the request plan. Both row-oriented and column-oriented tables are supported. Objects to which the full-scan concept does not apply (for example, topics) are not considered.
Details of full-scan detection:
-
LIMITdoes not cancel a full scan. Without a key condition, the physical plan processes the entire table;LIMITonly limits the size of the result. -
Secondary indexes. A full scan of a secondary index's implementation table is counted against its own path. For example, for the table
CREATE TABLE orders ( Id Uint64 NOT NULL, Status Utf8, PRIMARY KEY (Id), INDEX by_status GLOBAL ON (Status) );the index table has path
/Root/orders/by_status/indexImplTable. The querySELECT * FROM orders VIEW by_statusperforms a full scan of the index table тАФ the main/Root/ordersis not scanned. Therefore:HAS_FULL_SCAN='/Root/orders'тАФ will not match;HAS_FULL_SCAN='/Root/orders/by_status/indexImplTable'orHAS_FULL_SCAN='/Root/orders/*'тАФ will match.
Example. Reject requests that cause a full scan of the orders archive:
CREATE RESOURCE POOL CLASSIFIER cl_fullscan_reject WITH (
RANK=100,
ACTION='reject',
HAS_FULL_SCAN='/Root/db/orders_archive/*'
);
HAS_STREAM
HAS_STREAM determines whether a request is streaming тАФ that is, performs a long-running continuous read and/or write over data streams. Allowed values:
trueтАФ the classifier matches streaming requests;falseтАФ the classifier matches non-streaming requests.
Example. Direct streaming requests to the pool_stream pool:
CREATE RESOURCE POOL CLASSIFIER cl_stream WITH (
RANK=500,
RESOURCE_POOL='pool_stream',
HAS_STREAM=true
);
Notes
If RANK is not specified in the DDL for creating a resource pool classifier, it will be assigned the default value . All RANK values must be unique to ensure a strictly deterministic order of resource pool selection in case of conflicting conditions. This behavior is chosen to allow adding new resource pool classifiers between existing ones.
It is also possible to have a classifier that references a non-existent resource pool or one to which the user does not have access. In that case, it is skipped.
For limitations on the number of classifiers, see the limitations page.
Permissions
The permission USE on the database is required.
Example of granting such a permission:
GRANT 'USE' ON `/my_db` TO `user1@domain`;
Examples
Below is a combined example that composes several classifiers and predicates: rejecting full scans of archive tables, isolating streaming requests, and dedicating a pool for interactive admin queries from YDB UI.
Creating resource pools:
CREATE RESOURCE POOL pool_stream WITH (
TOTAL_CPU_LIMIT_PERCENT_PER_NODE=20
);
CREATE RESOURCE POOL pool_adhoc_admin WITH (
TOTAL_CPU_LIMIT_PERCENT_PER_NODE=10
);
Creating classifiers:
-- Reject full scans of archive tables.
CREATE RESOURCE POOL CLASSIFIER cl_fullscan_reject WITH (
RANK=100,
ACTION='reject',
HAS_FULL_SCAN='/Root/db/orders_archive/*'
);
-- Direct streaming requests to a dedicated pool.
CREATE RESOURCE POOL CLASSIFIER cl_stream WITH (
RANK=200,
RESOURCE_POOL='pool_stream',
HAS_STREAM=true
);
-- Admin requests from YDB UI — into the interactive-queries pool.
-- AND condition: both MEMBER_NAME and HAS_APP_NAME must match.
CREATE RESOURCE POOL CLASSIFIER cl_adhoc_admin WITH (
RANK=300,
RESOURCE_POOL='pool_adhoc_admin',
MEMBER_NAME='admin',
HAS_APP_NAME='ydb-ui'
);
Classifiers are processed in ascending order of RANK; the first matching classifier is applied to the request. A request that does not match any classifier is directed to the default pool.