Feature policies¶
A feature policy controls which object types can be created in a given context. You can apply a feature policy to all native apps in an account, to a specific native app, to all personal databases in an account, to all regular databases in an account, or to a specific database.
You can block every creation of a listed object type with
BLOCKED_OBJECT_TYPES_FOR_CREATION, or attach a YAML policy body with
conditional creation rules that fire only when a SQL expression
you supply evaluates to TRUE. For example, a feature policy can permit tables in general but
block temporary tables, or permit tasks but block serverless (no-warehouse) tasks.
Feature policies are schema-level objects. Before creating one, create a dedicated database and schema to store it.
For details on using feature policies with native apps, see Use feature policies to limit the objects an app can create.
For details on using feature policies with personal databases, see Use feature policies with personal databases.
Blockable object types¶
Account-level objects (native apps only)¶
When a native app is installed with automated granting of privileges, the app can receive privileges that let it create account-level objects such as warehouses, compute pools, and databases. Once granted, these privileges can’t be directly revoked by the consumer. A feature policy lets administrators prevent apps from exercising those privileges to create specific object types, without revoking the underlying privilege.
The following account-level object types can be blocked:
- COMPUTE_POOLS
- DATABASES
- WAREHOUSES
Note
Account-level object types have no effect when a feature policy is bound to personal databases. They apply only in a native app context.
Other blockable types¶
The following object types can be blocked in any context to which the policy is attached, whether that is native apps or personal databases:
- AGENTS
- APPLICATION_SERVICE
- ARTIFACT_REPOSITORY
- GIT_REPOSITORY
- MCP_SERVERS
- SCHEMA
- SECRET
- TASKS
- WORKSPACE
For the broader set of object types that conditional creation rules can reference, see Supported object types.
Privileges required to use feature policies¶
A role used to execute this operation must have the following privileges at a minimum:
| Privilege | Object | Notes |
|---|---|---|
| CREATE FEATURE POLICY | SCHEMA | Required to create a feature policy. This privilege must be granted on the schema containing the feature policy. |
| APPLY FEATURE POLICY | ACCOUNT | |
| APPLY or OWNERSHIP | FEATURE POLICY |
For instructions on creating a custom role with a specified set of privileges, see Creating custom roles.
For general information about roles and privilege grants for performing SQL actions on securable objects, see Overview of Access Control.
Create a feature policy¶
Use the CREATE FEATURE POLICY command to create a feature policy. The following example creates a policy that blocks task creation:
Note
Feature policies must be created within a schema.
You can also create a policy that doesn’t restrict any object types. This is useful for overriding a more general account-level policy on a specific app:
To create a policy with conditional creation rules, see Feature policy rules.
Apply a feature policy¶
To all native apps¶
To apply a feature policy to all native apps in the account, use the ALTER ACCOUNT command:
To replace an existing account-level policy without unsetting it first, use FORCE:
To unapply the policy from all native apps:
To a specific application¶
To apply a feature policy when installing an application, use the WITH FEATURE POLICY clause of
the CREATE APPLICATION command:
To apply a feature policy to an existing application, use the ALTER APPLICATION command:
To unapply the policy from a specific application:
A per-application policy overrides the account-level FOR ALL APPLICATIONS policy for that
application. See Feature policy precedence for details.
To all databases¶
To apply a feature policy to all regular databases in the account, use the
ALTER ACCOUNT command with FOR ALL DATABASES:
This policy also applies to personal databases as a fallback when no FOR ALL PERSONAL DATABASES
policy is set. It does not apply to native apps (application instances or application packages).
To replace an existing FOR ALL DATABASES policy without unsetting it first, use FORCE:
To unapply the policy from all databases:
To a specific database¶
To apply a feature policy to a specific database, use the ALTER DATABASE command:
To replace an existing database-level policy without unsetting it first, use FORCE:
To unapply the policy from the database:
A policy applied directly to a database overrides any account-level policy for that database. See Feature policy precedence for details.
To all personal databases¶
To apply a feature policy to all personal databases in the account, use the
ALTER ACCOUNT command with FOR ALL PERSONAL DATABASES:
To unapply the policy from all personal databases:
Note
The FOR ALL APPLICATIONS, FOR ALL PERSONAL DATABASES, and FOR ALL DATABASES bindings are
independent. Setting or unsetting one has no effect on the others.
Feature policy precedence¶
When an object is created, Snowflake walks the following hierarchy and enforces the first matching policy it finds. A more specific policy always wins over a more general one.
Regular databases¶
For objects created inside a regular database (not a personal database or application instance):
- A policy applied directly to the database (
ALTER DATABASE ... SET FEATURE POLICY) - The account-level
FOR ALL DATABASESpolicy - No policy applies — the creation is allowed.
Personal databases¶
For objects created inside a personal database:
- A policy applied directly to the database (
ALTER DATABASE ... SET FEATURE POLICY) - The account-level
FOR ALL PERSONAL DATABASESpolicy - The account-level
FOR ALL DATABASESpolicy (personal databases fall under this context when noFOR ALL PERSONAL DATABASESpolicy is set) - No policy applies — the creation is allowed.
Native apps (application instances)¶
For objects created inside a native app:
- A policy applied directly to the app (
ALTER APPLICATION ... SET FEATURE POLICYorCREATE APPLICATION ... WITH FEATURE POLICY) - The account-level
FOR ALL APPLICATIONSpolicy - No policy applies — the creation is allowed.
FOR ALL DATABASES does not apply to native apps (application instances or application packages).
Using an empty policy to lift restrictions¶
A policy with no blocked object types can be applied at any specific level to explicitly allow creation of all types, overriding a more general policy. For example, you can block a type for all databases at the account level while exempting a specific database from that restriction:
Feature policy rules¶
A feature policy can carry a YAML body that conditionally blocks the creation of
specific object types based on attributes of the request. This extends the
existing BLOCKED_OBJECT_TYPES_FOR_CREATION clause, which blocks every attempt
to create an object of a given type, with rules that fire only when a SQL
expression you supply evaluates to TRUE.
Policy body syntax¶
The body is a YAML document attached to the policy with an AS clause:
The YAML supports two top-level keys:
blocked_creation_rules:A list of rules, each scoped to a single
object_type(for example,TABLE,TASK,WAREHOUSE) or to theALLwildcard. A rule blocks creation when itsblock_whenexpression evaluates toTRUE, or when any of the conditions named inblock_when_anyevaluates toTRUE. If bothblock_whenandblock_when_anyare omitted, every creation of thatobject_typeis blocked (this isn’t allowed forALL; see Supported object types). A rule can specifyblock_whenorblock_when_any, but not both.conditions:An optional list of named, reusable expressions that rules can reference by name through
block_when_any. Use this when the same predicate appears in multiple rules. A rule that usesblock_when_anyrequires at least one matching entry inconditions.
Supported object types¶
A rule’s object_type can name any of the following types, in either singular
or plural form (for example, both TABLE and TABLES are accepted):
| Category | Object types |
|---|---|
| Account-level | COMPUTE_POOL, DATABASE, WAREHOUSE |
| Schema-level | TABLE, ICEBERG_TABLE, DYNAMIC_TABLE, MATERIALIZED_VIEW, VIEW, STAGE, FILE_FORMAT, FUNCTION, PROCEDURE, SECRET, SCHEMA, TASK, AGENT, MCP_SERVER |
| Personal database | WORKSPACE, GIT_REPOSITORY, APPLICATION_SERVICE, ARTIFACT_REPOSITORY |
Account-level types apply only in a native app context. Personal database types apply only
when the policy is bound to personal databases, either with FOR ALL PERSONAL DATABASES or
directly to a personal database. The ALL wildcard covers only the types applicable in the
current policy binding context.
A rule can also use the ALL wildcard in place of a specific object_type to
apply a single block_when or block_when_any to every supported type. An
ALL rule must carry a block_when or block_when_any: an unconditional ALL
rule (one that blocks every object type outright) isn’t allowed. To block every
creation of a specific type unconditionally, list that type in
BLOCKED_OBJECT_TYPES_FOR_CREATION instead.
Supported object types for personal databases¶
Within a personal-database policy, blocked_creation_rules can reference the following
entity types:
| Category | Object types |
|---|---|
| Account-level | (none; account-level types have no effect in personal database context) |
| Entity types | WORKSPACE, SCHEMA, SECRET, GIT_REPOSITORY, APPLICATION_SERVICE, ARTIFACT_REPOSITORY |
Account-level types (COMPUTE_POOL, DATABASE, WAREHOUSE) are ignored when a policy
is bound to personal databases. List them in BLOCKED_OBJECT_TYPES_FOR_CREATION or
blocked_creation_rules only when the policy is bound to native apps. For how Snowflake
chooses between a per-database policy and an account-level policy, see
Feature policy precedence.
block_ when expressions¶
A block_when (or conditions[].expression) value is a SQL Boolean expression
written as a quoted string. The expression is validated when the policy is
created or altered.
Available context¶
Refer to attributes of the object being created with
SYS_CONTEXT('SNOWFLAKE$REQUEST', 'GET_OBJECT_PROPERTY', '<property>'). The
function returns a string, so compare against 'TRUE' or 'FALSE' for Boolean
properties.
| Property | Type | Returns |
|---|---|---|
IS_TEMPORARY | Boolean | 'TRUE' for CREATE TEMPORARY ... of TABLE, VIEW, STAGE, FILE_FORMAT, FUNCTION, PROCEDURE, SECRET, AGENT; 'FALSE' otherwise. |
IS_TRANSIENT | Boolean | 'TRUE' for CREATE TRANSIENT ... of TABLE, ICEBERG_TABLE, DYNAMIC_TABLE, MATERIALIZED_VIEW, SCHEMA, DATABASE, APPLICATION_PACKAGE; 'FALSE' otherwise. |
WAREHOUSE | String | For TASK: the warehouse named in the request, or NULL if none (serverless task). NULL for other object types. |
EXTERNAL_VOLUME | String | For ICEBERG_TABLE: the external volume resolved for the request (table, schema, database, or account level), or NULL if none. NULL for other object types. |
DATABASE | String | The name of the database containing the object being created. NULL for account-level object types. |
SCHEMA | String | The name of the schema containing the object being created. NULL for account-level and database-level object types (those not contained in a schema, including SCHEMA itself). |
Boolean properties always return 'TRUE' or 'FALSE' for every object type,
so a single IS_TEMPORARY or IS_TRANSIENT rule applied across mixed object
types behaves predictably: the property is 'FALSE' for object types that
can’t be temporary or transient (for example, IS_TRANSIENT is 'FALSE' for
STAGE).
String properties return NULL when the rule’s object_type doesn’t carry
that property. A comparison against NULL is itself NULL, and a rule whose
block_when evaluates to NULL fails closed and blocks the operation (see
NULL handling). Guard string-property
comparisons so they evaluate to TRUE or FALSE for every object_type the
rule covers.
Validation rules¶
The following expressions are rejected at CREATE or ALTER time:
- Expressions that don’t evaluate to a Boolean type (for example, a numeric literal or a string literal).
- Expressions that reference tables or other database objects (for example,
(SELECT COUNT(*) FROM t) > 0). - Expressions that call functions with side effects (for example,
SYSTEM$RUN_QUERY_SYNC). - Expressions that name an unsupported
object_typeor call a function that doesn’t exist.
NULL handling¶
If block_when evaluates to NULL at runtime (for example, because
SYS_CONTEXT(...) = 'TRUE' is compared against a property the request didn’t
supply), the rule fails closed: the operation is blocked. Write expressions
that always evaluate to TRUE or FALSE for every object_type a rule
covers, for example by guarding a property comparison with a test that is
never NULL.
Examples¶
The following examples assume the feature policy is attached to an account, an application, or a database after creation. For attachment syntax, see Apply a feature policy.
Block all temporary tables¶
Block all transient tables¶
Transient tables don’t carry the same Time Travel and Fail-safe protections as
permanent tables. A policy that requires only permanent tables can block
creations of CREATE TRANSIENT TABLE:
To require permanent tables outright, block both temporary and transient creations in the same rule:
Block transient and temporary objects across multiple object types¶
A single named condition can be reused across object types, including object
types that don’t support TRANSIENT (such as STAGE, VIEW, FUNCTION,
PROCEDURE). For those types, IS_TRANSIENT is 'FALSE', so the rule fires
only on temporary creations:
Block serverless tasks¶
Serverless tasks are tasks created without a WAREHOUSE. The following policy
permits warehouse-attached tasks but blocks serverless ones:
Block a property across every object type with ALL¶
Use the ALL wildcard to apply one rule to every supported object type without
listing each one. Because Boolean properties such as IS_TEMPORARY are 'FALSE'
for object types that can’t be temporary, the following policy blocks every
temporary creation across all types and permits everything else:
An ALL rule must include a block_when or block_when_any. To block every
creation of a type unconditionally, list it in
BLOCKED_OBJECT_TYPES_FOR_CREATION instead.
Restrict object creation to a specific schema¶
Use the SCHEMA context property to block creations outside an approved schema.
A schema-level object such as a table always carries a SCHEMA value, so the
comparison never evaluates to NULL:
The SCHEMA property returns the schema name as stored in the catalog (uppercase
unless the schema was created with a quoted, case-sensitive identifier). The
companion DATABASE property restricts by containing database in the same way.
Block every table¶
Omit block_when to block every creation of an object type, regardless of
request attributes:
Reuse a condition across rules¶
Combine type-level blocks and rules¶
BLOCKED_OBJECT_TYPES_FOR_CREATION and blocked_creation_rules can be used
together in a single policy. Listing an object type in
BLOCKED_OBJECT_TYPES_FOR_CREATION blocks every creation of that type
regardless of any rule. Rules covering different object types are evaluated
independently. The following policy blocks every warehouse creation and also
blocks temporary tables:
Modify or remove a policy body¶
Use ALTER FEATURE POLICY to set, replace, or clear the body of an existing policy.
To replace the body, use the AS clause, with or without other SET clauses:
To remove the body but keep any BLOCKED_OBJECT_TYPES_FOR_CREATION clause:
To inspect the current body, use
DESCRIBE FEATURE POLICY. The body appears as the
policy_definition property in the result.
Delete a feature policy¶
Use the DROP FEATURE POLICY command:
A feature policy can’t be dropped if it’s currently applied to an object. Unapply it first using ALTER ACCOUNT, ALTER APPLICATION, or ALTER DATABASE, then drop it.
View feature policies¶
To list the feature policies in the account that you have access to:
To list the feature policies applied to a specific application:
To list the feature policies applied to a specific database:
To view the details of a specific feature policy:
Identify feature policy references¶
The POLICY_REFERENCES Information Schema table function can identify feature policy references. There are two different syntax options:
-
Return a row for each object that has the specified feature policy assigned to it:
-
Return each feature policy assigned to the account:
Replication considerations¶
Feature policy references at the account level are replicated when the database containing the
policy is included in the replication group, for example by setting
ALLOWED_DATABASES = feature_policy_db.
If the account has already been replicated to a target account, do the following:
- Update the replication or failover group in the source account to include the databases and object types required to replicate the feature policy.
- Execute a refresh operation to update the target account.
Note
The feature policy must be in the same account as the account-level policy assignment.
If you don’t include the policy database in the replication group, Snowflake creates a dangling reference in the target account. The fully-qualified policy name points to the source account’s database, which doesn’t exist in the target account, so the policy isn’t enforced there.
For more information, see Replication considerations.