Home Database Data Governance: Classification, Tagging & Data Quality
Advanced 3 min · July 17, 2026

Data Governance: Classification, Tagging & Data Quality

Master Snowflake data governance with object tagging, classification, and data quality monitoring.

N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Drawn from code that ran under real load.

Follow
Production
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
Before you start⏱ 15-20 min read
  • Basic SQL knowledge (SELECT, ALTER, CREATE)
  • Access to a Snowflake account with ACCOUNTADMIN or equivalent privileges
  • Understanding of Snowflake roles and warehouses
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Use object tagging to attach metadata (e.g., PII, sensitivity) to columns, tables, and views.
  • Leverage System $TAG_REFERENCES and TAG_REFERENCE_ALL_COLUMNS functions to query tags.
  • Automate classification with stored procedures that scan column names and data patterns.
  • Monitor data quality with custom metrics and alerts using Snowflake tasks and alerts.
  • Enforce governance via tag-based masking policies and row access policies.
✦ Definition~90s read
What is Data Governance?

Snowflake data governance is the practice of managing metadata, enforcing policies, and monitoring data quality using object tagging, classification, and automated alerts.

Think of Snowflake data governance like a library.
Plain-English First

Think of Snowflake data governance like a library. Tags are color-coded stickers on books (columns) that say 'Confidential' or 'Public'. Classification is the librarian sorting books into sections. Data quality is checking that no pages are missing. Together, they keep the library organized and trustworthy.

In today's data-driven world, organizations collect vast amounts of data, but without proper governance, that data can become a liability. Snowflake's data governance features—object tagging, classification, and data quality monitoring—provide a robust framework to manage metadata, enforce policies, and ensure data trustworthiness. This tutorial dives deep into practical implementation, from tagging sensitive columns to automating classification and monitoring data quality. You'll learn how to use Snowflake's system functions, create dynamic masking policies based on tags, and set up alerts for data anomalies. By the end, you'll be equipped to build a production-ready governance layer that scales with your data warehouse.

Understanding Snowflake Object Tagging

Object tagging in Snowflake allows you to assign key-value pairs to database objects like columns, tables, views, and schemas. Tags are metadata that can be used for governance, cost tracking, and security. For example, you can tag a column with 'sensitive = true' or 'pii = email'. Tags are stored in the Snowflake metadata layer and can be queried using system functions. To create a tag, use CREATE TAG. To apply a tag, use ALTER ... SET TAG. Tags support inheritance: if you tag a schema, all objects in that schema inherit the tag unless overridden. This is powerful for applying policies at scale. However, inheritance is not automatic for all operations; you must explicitly set tags on new objects or rely on classification procedures.

tag_creation.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
-- Create a tag for sensitivity levels
CREATE TAG IF NOT EXISTS sensitivity_level
  ALLOWED_VALUES 'high', 'medium', 'low';

-- Apply tag to a column
ALTER TABLE orders MODIFY COLUMN customer_email SET TAG sensitivity_level = 'high';

-- Query tag references
SELECT * FROM TABLE(INFORMATION_SCHEMA.TAG_REFERENCES('orders', 'TABLE'));

-- Use system function
SELECT SYSTEM$TAG_REFERENCE('orders', 'TABLE', 'sensitivity_level');
Output
+----------------+----------------+----------------+----------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE |
+----------------+----------------+----------------+----------------+
| MYDB | PUBLIC | SENSITIVITY_LEVEL | HIGH |
+----------------+----------------+----------------+----------------+
💡Tag Naming Conventions
📊 Production Insight
Tagging a schema applies tags to all existing objects, but new objects must be tagged explicitly. Automate with a classification procedure.
🎯 Key Takeaway
Object tagging is the foundation of Snowflake governance; use ALLOWED_VALUES to enforce controlled vocabularies.

Automated Data Classification with Stored Procedures

Manual tagging doesn't scale. Automate classification using a stored procedure that scans column names and sample data to apply tags. For example, columns named 'email', 'ssn', or containing patterns like '@' can be tagged as PII. Use Snowflake's JavaScript stored procedures to iterate over tables and columns. The procedure can query INFORMATION_SCHEMA.COLUMNS and apply tags using ALTER TABLE ... SET TAG. Schedule it with a task to run daily. This ensures new columns are classified promptly. You can also use Snowflake's built-in classification function (SYSTEM$CLASSIFY) but it's limited; custom procedures give more control.

classification_procedure.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
CREATE OR REPLACE PROCEDURE classify_columns()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
AS
$$
  var result = '';
  var tables = snowflake.execute({
    sqlText: `SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE
              FROM INFORMATION_SCHEMA.COLUMNS
              WHERE TABLE_SCHEMA = 'PUBLIC'`
  });
  while (tables.next()) {
    var catalog = tables.getColumnValue(1);
    var schema = tables.getColumnValue(2);
    var table = tables.getColumnValue(3);
    var column = tables.getColumnValue(4);
    var type = tables.getColumnValue(5);
    var tagValue = 'low';
    if (column.match(/email|ssn|phone|credit/i)) {
      tagValue = 'high';
    } else if (type === 'VARCHAR' && column.match(/name|address/i)) {
      tagValue = 'medium';
    }
    var alterSQL = `ALTER TABLE ${catalog}.${schema}.${table} MODIFY COLUMN ${column} SET TAG sensitivity_level = '${tagValue}'`;
    try {
      snowflake.execute({sqlText: alterSQL});
      result += 'Tagged ' + column + ' as ' + tagValue + '\\n';
    } catch(err) {
      result += 'Error tagging ' + column + ': ' + err + '\\n';
    }
  }
  return result;
$$;

-- Schedule with a task
CREATE OR REPLACE TASK classify_task
  WAREHOUSE = my_wh
  SCHEDULE = 'USING CRON 0 6 * * * UTC'
AS
  CALL classify_columns();

ALTER TASK classify_task RESUME;
Output
Tagged CUSTOMER_EMAIL as high
Tagged CUSTOMER_NAME as medium
Tagged SSN as high
⚠ Performance Consideration
📊 Production Insight
Consider using Snowflake's CLASSIFY function for initial classification, but custom procedures allow domain-specific rules.
🎯 Key Takeaway
Automate classification with a stored procedure and schedule it as a task to keep tags up-to-date.

Enforcing Governance with Tag-Based Masking Policies

Masking policies in Snowflake can be attached to tags, not just columns. This allows dynamic masking based on tag values. For example, create a masking policy that masks columns tagged with 'sensitivity_level = high' for non-privileged roles. To attach a policy to a tag, use ALTER TAG ... SET MASKING POLICY. When a column has that tag, the policy automatically applies. This decouples policy from specific columns, making governance scalable. You can also use conditional masking based on the tag value. For instance, mask 'high' columns fully, 'medium' partially, and 'low' not at all.

tag_based_masking.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Create masking policy that masks based on role
CREATE OR REPLACE MASKING POLICY mask_high AS (val VARCHAR) RETURNS VARCHAR ->
  CASE
    WHEN CURRENT_ROLE() IN ('ADMIN', 'COMPLIANCE') THEN val
    ELSE '***MASKED***'
  END;

-- Attach policy to tag
ALTER TAG sensitivity_level SET MASKING POLICY mask_high;

-- Now any column with tag sensitivity_level = 'high' will be masked for non-privileged roles.
-- Test as analyst role
USE ROLE ANALYST;
SELECT customer_email FROM orders; -- returns '***MASKED***'
Output
+----------------+
| CUSTOMER_EMAIL |
+----------------+
| ***MASKED*** |
+----------------+
🔥Policy Inheritance
📊 Production Insight
Test masking policies with different roles in a non-production environment to avoid accidental data exposure.
🎯 Key Takeaway
Attach masking policies to tags to automatically secure all columns with that tag, reducing manual effort.

Data Quality Monitoring with Alerts and Tasks

Data quality is crucial for trust. Snowflake provides alerts (CREATE ALERT) that can monitor conditions like NULL rates, value ranges, or freshness. For example, alert if the 'order_amount' column has NULLs more than 1% of rows. Use tasks to compute quality metrics and store them in a table, then set alerts on that table. You can also use Snowflake's built-in data quality functions like COUNT, AVG, and STDDEV. Alerts can send notifications via email or webhook. This proactive monitoring catches issues before they affect downstream consumers.

data_quality_alert.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- Create a table to store quality metrics
CREATE TABLE quality_metrics (
  table_name VARCHAR,
  column_name VARCHAR,
  null_count NUMBER,
  total_rows NUMBER,
  null_ratio FLOAT,
  checked_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP()
);

-- Task to compute metrics daily
CREATE OR REPLACE TASK compute_quality
  WAREHOUSE = my_wh
  SCHEDULE = 'USING CRON 0 7 * * * UTC'
AS
  INSERT INTO quality_metrics (table_name, column_name, null_count, total_rows, null_ratio)
  SELECT 'orders', 'order_amount',
         COUNT(*)-COUNT(order_amount),
         COUNT(*),
         (COUNT(*)-COUNT(order_amount))/NULLIF(COUNT(*),0)
  FROM orders;

-- Alert if null ratio > 0.01
CREATE OR REPLACE ALERT high_null_rate
  WAREHOUSE = my_wh
  SCHEDULE = 'USING CRON 0 8 * * * UTC'
  IF (EXISTS (
    SELECT 1 FROM quality_metrics
    WHERE null_ratio > 0.01 AND checked_at >= CURRENT_TIMESTAMP() - INTERVAL '1 day'
  ))
  THEN
    CALL SYSTEM$SEND_EMAIL('governance@company.com', 'High NULL rate detected', 'Check quality_metrics table.');

ALTER TASK compute_quality RESUME;
ALTER ALERT high_null_rate RESUME;
Output
Alert triggered: High NULL rate detected
💡Alert Best Practices
📊 Production Insight
Store quality metrics in a separate schema to avoid impacting production workloads. Use a dedicated warehouse for compute.
🎯 Key Takeaway
Combine tasks and alerts to continuously monitor data quality and get notified of anomalies.

Auditing Tag Coverage and Compliance

Regular audits ensure governance policies are followed. Use Snowflake's TAG_REFERENCE_ALL_COLUMNS function to list all columns and their tags. Compare against a baseline of expected tags. You can also use INFORMATION_SCHEMA.TAG_REFERENCES to check specific objects. Create a dashboard or report that shows untagged columns, especially in critical schemas. Automate this with a task that generates a report and sends it via email. Compliance requirements like GDPR or HIPAA often mandate tagging of sensitive data, so audits are essential.

audit_tag_coverage.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
-- Find all columns without a specific tag
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME) NOT IN (
  SELECT OBJECT_DATABASE, OBJECT_SCHEMA, OBJECT_NAME, COLUMN_NAME
  FROM TABLE(INFORMATION_SCHEMA.TAG_REFERENCES_ALL_COLUMNS())
  WHERE TAG_NAME = 'SENSITIVITY_LEVEL'
)
AND TABLE_SCHEMA = 'PUBLIC';

-- List all tags applied to columns
SELECT * FROM TABLE(INFORMATION_SCHEMA.TAG_REFERENCES_ALL_COLUMNS())
WHERE TAG_NAME = 'SENSITIVITY_LEVEL';
Output
+----------------+----------------+------------+----------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME |
+----------------+----------------+------------+----------------+
| MYDB | PUBLIC | ORDERS | DISCOUNT_CODE |
+----------------+----------------+------------+----------------+
🔥Automate Audits
📊 Production Insight
Use TAG_REFERENCES_ALL_COLUMNS sparingly on large accounts; it can be expensive. Filter by schema or database.
🎯 Key Takeaway
Regularly audit tag coverage to identify gaps and ensure compliance with data governance policies.

Integrating with Row Access Policies

Tags can also drive row-level security via row access policies. For example, if a table has a tag 'region' on a column, you can create a row access policy that filters rows based on the user's region. Combine with mapping tables to map tags to access privileges. This allows fine-grained access control without modifying queries. Row access policies are attached to tables, and they can reference tag values indirectly through context functions or mapping tables.

row_access_with_tags.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- Assume a mapping table that links tag values to roles
CREATE TABLE region_access (
  region_tag VARCHAR,
  allowed_role VARCHAR
);
INSERT INTO region_access VALUES ('US', 'ANALYST_US'), ('EU', 'ANALYST_EU');

-- Row access policy that filters based on current role
CREATE OR REPLACE ROW ACCESS POLICY region_filter AS (region_tag VARCHAR) RETURNS BOOLEAN ->
  EXISTS (
    SELECT 1 FROM region_access
    WHERE region_tag = region_tag
      AND allowed_role = CURRENT_ROLE()
  );

-- Apply policy to table (assuming table has a column 'region' tagged with 'region_tag')
ALTER TABLE sales ADD ROW ACCESS POLICY region_filter ON (region);

-- Now users only see rows where their role matches the region tag.
Output
SELECT * FROM sales; -- Only rows for user's region
⚠ Performance Impact
📊 Production Insight
Keep mapping tables small and indexed. Consider caching mappings in a secure view.
🎯 Key Takeaway
Combine tags with row access policies to implement dynamic, attribute-based access control.

Best Practices and Governance Workflow

Implementing data governance in Snowflake requires a structured workflow: 1) Define tag taxonomy (e.g., sensitivity, data domain, retention). 2) Automate classification with stored procedures. 3) Enforce policies via tag-based masking and row access. 4) Monitor data quality with alerts. 5) Audit regularly. Use Snowflake's built-in governance features like Access History and Query Profile to track usage. Document your tagging conventions and train your team. Consider using a data catalog tool for broader governance. Remember that governance is an ongoing process, not a one-time setup.

governance_workflow.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- Example: Create a governance dashboard view
CREATE OR REPLACE VIEW governance_dashboard AS
SELECT 
  t.TABLE_CATALOG,
  t.TABLE_SCHEMA,
  t.TABLE_NAME,
  COUNT(DISTINCT c.COLUMN_NAME) AS total_columns,
  COUNT(DISTINCT tr.COLUMN_NAME) AS tagged_columns,
  COUNT(DISTINCT c.COLUMN_NAME) - COUNT(DISTINCT tr.COLUMN_NAME) AS untagged_columns
FROM INFORMATION_SCHEMA.TABLES t
JOIN INFORMATION_SCHEMA.COLUMNS c ON t.TABLE_CATALOG = c.TABLE_CATALOG AND t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.TABLE_NAME = c.TABLE_NAME
LEFT JOIN TABLE(INFORMATION_SCHEMA.TAG_REFERENCES_ALL_COLUMNS()) tr 
  ON c.TABLE_CATALOG = tr.OBJECT_DATABASE AND c.TABLE_SCHEMA = tr.OBJECT_SCHEMA AND c.TABLE_NAME = tr.OBJECT_NAME AND c.COLUMN_NAME = tr.COLUMN_NAME
WHERE t.TABLE_SCHEMA = 'PUBLIC'
GROUP BY t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME;
Output
+----------------+----------------+------------+---------------+----------------+------------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TOTAL_COLUMNS | TAGGED_COLUMNS | UNTAGGED_COLUMNS |
+----------------+----------------+------------+---------------+----------------+------------------+
| MYDB | PUBLIC | ORDERS | 10 | 8 | 2 |
+----------------+----------------+------------+---------------+----------------+------------------+
💡Start Small
📊 Production Insight
Involve data stewards and security teams early. Governance is a cross-functional effort.
🎯 Key Takeaway
A systematic workflow—taxonomy, automation, enforcement, monitoring, auditing—ensures sustainable governance.
● Production incidentPOST-MORTEMseverity: high

The PII Leak That Wasn't Caught by Tags

Symptom
Customer support emails appeared in a public-facing analytics dashboard.
Assumption
The developer assumed all PII columns were already tagged and masked.
Root cause
A new column 'customer_email' was added to the 'orders' table but not tagged with 'PII'. The masking policy only applied to tagged columns.
Fix
Implemented an automated classification stored procedure that runs daily, scanning new columns for patterns (e.g., email regex) and applying appropriate tags. Also added a tag-based alert to notify governance team of untagged columns.
Key lesson
  • Always tag new columns immediately; automate with a classification procedure.
  • Use tag-based masking policies so that untagged columns are not automatically exposed.
  • Set up alerts for untagged columns to catch governance gaps early.
  • Regularly audit tag coverage with system functions like TAG_REFERENCE_ALL_COLUMNS.
  • Include tag validation in your CI/CD pipeline for schema changes.
Production debug guideSymptom to Action4 entries
Symptom · 01
Masking policy not applied to a column
Fix
Check if the column has the required tag using TAG_REFERENCE_ALL_COLUMNS. Verify the masking policy is attached to the tag, not the column directly.
Symptom · 02
Data quality alert firing too often
Fix
Review the alert condition thresholds. Use a task to compute statistics and adjust thresholds based on historical data.
Symptom · 03
Classification procedure missing new columns
Fix
Check the procedure's schedule (e.g., CRON). Ensure it queries INFORMATION_SCHEMA.COLUMNS for all tables and applies tags based on column names and data patterns.
Symptom · 04
Tag not visible in query results
Fix
Verify the tag exists and is applied. Use SHOW TAGS and SELECT SYSTEM$TAG_REFERENCE(...). Ensure you have the MANAGE TAGS privilege.
★ Quick Debug Cheat SheetCommon governance issues and immediate actions
Column not masked
Immediate action
Check tag existence
Commands
SELECT SYSTEM$TAG_REFERENCE('DB.SCHEMA.TABLE', 'COLUMN');
SHOW TAGS;
Fix now
Apply the required tag: ALTER TABLE ... SET TAG ... = '...';
Data quality alert false positive+
Immediate action
Check alert definition
Commands
SHOW ALERTS;
SELECT * FROM INFORMATION_SCHEMA.ALERT_HISTORY WHERE ALERT_NAME = '...';
Fix now
Modify alert condition: ALTER ALERT ... SET CONDITION = ...;
Classification procedure not running+
Immediate action
Check task status
Commands
SHOW TASKS;
SELECT * FROM INFORMATION_SCHEMA.TASK_HISTORY WHERE TASK_NAME = '...';
Fix now
Resume task: ALTER TASK ... RESUME;
FeatureObject TaggingMasking PolicyRow Access Policy
PurposeAttach metadataMask column dataFilter rows
ScopeColumns, tables, schemas, etc.Columns (or tags)Tables
DynamicNoYes (based on role)Yes (based on condition)
Tag-basedN/AYes (attach to tag)Indirectly via mapping
⚙ Quick Reference
7 commands from this guide
FileCommand / CodePurpose
tag_creation.sqlCREATE TAG IF NOT EXISTS sensitivity_levelUnderstanding Snowflake Object Tagging
classification_procedure.sqlCREATE OR REPLACE PROCEDURE classify_columns()Automated Data Classification with Stored Procedures
tag_based_masking.sqlCREATE OR REPLACE MASKING POLICY mask_high AS (val VARCHAR) RETURNS VARCHAR ->Enforcing Governance with Tag-Based Masking Policies
data_quality_alert.sqlCREATE TABLE quality_metrics (Data Quality Monitoring with Alerts and Tasks
audit_tag_coverage.sqlSELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAMEAuditing Tag Coverage and Compliance
row_access_with_tags.sqlCREATE TABLE region_access (Integrating with Row Access Policies
governance_workflow.sqlCREATE OR REPLACE VIEW governance_dashboard ASBest Practices and Governance Workflow

Key takeaways

1
Object tagging is the foundation of Snowflake governance; use ALLOWED_VALUES and automate classification.
2
Tag-based masking policies scale governance by applying policies to all columns with a given tag.
3
Data quality monitoring with alerts and tasks ensures data trustworthiness.
4
Regular audits of tag coverage prevent governance gaps.
5
Combine tags with row access policies for attribute-based access control.

Common mistakes to avoid

3 patterns
×

Applying tags directly to columns without using ALLOWED_VALUES

×

Attaching masking policies to tags but forgetting to set the tag on new columns

×

Using the same tag for multiple purposes (e.g., sensitivity and data domain)

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the difference between a tag and a label in Snowflake?
Q02SENIOR
How do you enforce that all new columns in a schema are automatically ta...
Q03SENIOR
Explain how tag-based masking policies work and their advantages over co...
Q01 of 03JUNIOR

What is the difference between a tag and a label in Snowflake?

ANSWER
Snowflake uses 'tag' as the official term. There is no separate 'label' concept. Tags are key-value pairs attached to objects.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I apply multiple tags to the same column?
02
How do I remove a tag from a column?
03
What happens if I drop a tag that is attached to a masking policy?
04
Can I use tags for cost tracking?
05
How do I see all tags in my account?
N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Drawn from code that ran under real load.

Follow
Verified
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
🔥

That's Snowflake. Mark it forged?

3 min read · try the examples if you haven't

Previous
Hybrid Tables and Unistore: Transactional Workloads on Snowflake
28 / 33 · Snowflake
Next
Differential Privacy: Privacy-Preserving Data Analysis