Enterprise Governance and Operating Model for Snowflake Horizon Context
Last Updated on July 6, 2026 by Editorial Team
Author(s): Satish Kumar
Originally published on Towards AI.
Part 4 of a series on implementing Snowflake Horizon Context in production
You Built It. Now What?
Parts 1–3 of this series covered the technical stack: semantic layer foundations, governance frameworks, and AI agent activation. If you followed along, you now have certified metrics, governed Semantic Views, and Cortex Agents delivering grounded answers with full provenance.
Congratulations. You’ve solved the easy problem.

The hard problem is what kills semantic layers at scale: nobody knows who approves new metrics, views go stale because ownership isn’t enforced, three teams define “active customer” differently and nobody notices, the governance process takes six weeks so teams bypass it, and AI agents inherit conflicting definitions from abandoned views.
This isn’t a technology problem. It’s an organizational one. And it’s the reason most enterprise semantic layers collapse under their own weight within 18 months.
This article provides the operating model that prevents that collapse — and then makes it completely autonomous. We’ll cover role architecture, RACI matrices, DevOps pipelines, compliance automation, scaling patterns, operating cadences, governance health metrics, self-service onboarding, automated validation engines, alerting, and auto-remediation — everything needed to run a semantic layer across a 10,000-person organization without governance becoming a bottleneck.
The Three Axes of Semantic Governance
Every governance operation touches three distinct concerns:
- Domain expertise — who knows what the metric means
- Technical capability — who can change the implementation
- Approval authority — who can certify for production use
The critical design principle: no single role should hold all three. This is separation of duties applied to the semantic layer.
When one person both defines a revenue metric and approves it for production, you’ve created a single point of failure with no checks. When that person leaves, you’ve created an orphaned metric with no one who understands why it was defined that way.
Role Hierarchy for a 10,000-Person Enterprise
GOVERNANCE_COUNCIL_ADMIN
(CDO / VP Data — 1-2 people)
|
+--------------+--------------+
| | |
DOMAIN PLATFORM COMPLIANCE
STEWARD ENGINEER OFFICER
(per BU) (per team) (per regulation)
| | |
METRIC SEMANTIC AUDIT
OWNER DEVELOPER REVIEWER
(per metric) (per domain) (read-only)
| |
+--------------+
|
METRIC_CONSUMER
(analysts, data scientists, AI agents)
In Snowflake, this maps directly to RBAC:
-- Top-level authority (break-glass only)
CREATE ROLE IF NOT EXISTS governance_council_admin;
-- Domain stewards: one per business unit
CREATE ROLE IF NOT EXISTS domain_steward_finance;
CREATE ROLE IF NOT EXISTS domain_steward_sales;
CREATE ROLE IF NOT EXISTS domain_steward_cs;
CREATE ROLE IF NOT EXISTS domain_steward_product;
CREATE ROLE IF NOT EXISTS domain_steward_hr;
-- Platform engineering
CREATE ROLE IF NOT EXISTS semantic_platform_admin;
CREATE ROLE IF NOT EXISTS semantic_developer;
-- Compliance and audit
CREATE ROLE IF NOT EXISTS compliance_officer;
CREATE ROLE IF NOT EXISTS audit_reviewer;
-- Consumers (tiered)
CREATE ROLE IF NOT EXISTS metric_consumer_full;
CREATE ROLE IF NOT EXISTS metric_consumer_internal;
CREATE ROLE IF NOT EXISTS metric_consumer_restricted;
-- AI agent service accounts (non-human principals)
CREATE ROLE IF NOT EXISTS agent_service_finance;
CREATE ROLE IF NOT EXISTS agent_service_sales;
CREATE ROLE IF NOT EXISTS agent_service_executive;
The key insight: AI agents are first-class participants in the role hierarchy. They get their own service roles with explicit, auditable access — not implicit access through a shared service account.
RACI: Who Does What, For Every Operation
Ambiguity in governance kills governance. The moment someone asks “who approves this?” and three people shrug, you’ve lost.
We store the RACI matrix as structured data — queryable, reportable, and enforceable:
CREATE OR REPLACE TABLE governance.operating_model.raci_matrix (
operation_name VARCHAR NOT NULL,
operation_category VARCHAR NOT NULL,
responsible_role VARCHAR NOT NULL, -- Does the work
accountable_role VARCHAR NOT NULL, -- Final authority (exactly ONE)
consulted_roles ARRAY, -- Must be asked before action
informed_roles ARRAY, -- Notified after action
sla_hours INTEGER, -- Max time from request to completion
escalation_path VARCHAR,
requires_approval BOOLEAN DEFAULT TRUE,
minimum_approvers INTEGER DEFAULT 1,
notes TEXT
);
The 13 Operations That Need Governance
| Category | Operation | Responsible | Accountable | SLA | Approvers |
| ------------- | --------------------------- | ------------------ | -------------- | ---- | --------- |
| Creation | New metric definition | Metric Owner | Domain Steward | 72h | 1 |
| Creation | New semantic view | Semantic Developer | Platform Admin | 48h | 2 |
| Creation | New AI agent | Semantic Developer | Platform Admin | 120h | 3 |
| Change | Non-breaking metric change | Metric Owner | Domain Steward | 48h | 1 |
| Change | Breaking metric change | Metric Owner | Council Admin | 168h | 3 |
| Change | Agent instruction update | Semantic Developer | Platform Admin | 48h | 2 |
| Deployment | Semantic view to production | Semantic Developer | Platform Admin | 24h | 2 |
| Deployment | Agent to production | Semantic Developer | Platform Admin | 24h | 2 |
| Certification | Initial certification | Metric Owner | Domain Steward | 120h | 2 |
| Certification | Quarterly recertification | Metric Owner | Domain Steward | 168h | 1 |
| Deprecation | Metric deprecation | Domain Steward | Council Admin | 720h | 2 |
| Incident | Wrong number from agent | Platform Admin | Domain Steward | 4h | 0 |
| Incident | Data quality failure | Semantic Developer | Platform Admin | 8h | 0 |
Table : Semantic Layer Governance Operating Model covering creation, change management, deployment, certification, deprecation, and incident response workflows.
Notice the asymmetry: creating a new agent requires 3 approvers and 120 hours, but responding to a wrong-number incident requires 0 approvers and 4 hours. The governance bar is highest for decisions with wide blast radius and lowest for decisions requiring immediate action.
The breaking metric change — modifying calculation logic, joins, or filters — escalates all the way to the Governance Council Admin (CDO) and requires 7 days for impact assessment. This is intentional friction. If changing a metric’s math is easy, metrics will change constantly and downstream consumers will lose trust.
DevOps for Semantic Assets
Semantic views, agent specifications, metric definitions, and test cases are code. They deserve the same rigor as application code:
- Version control (Git)
- Branch-based development
- Automated testing (CI)
- Promotion gates (CD)
- Rollback capability
- Change history and blame
Three-Environment Topology
EnvironmentPurposeAgent ModePromotion RequiresDEVSandbox for authoringDisabledSemantic DeveloperSTAGINGIntegration testing with production-like dataShadow modePlatform Admin + Domain StewardPRODUCTIONCertified assets serving consumers and agentsLivePlatform Admin + Domain Steward + Compliance Officer
Promotion Gates
The pipeline from DEV to PRODUCTION has 10 gates — 6 automated, 4 requiring human approval:
DEV → STAGING (automated):
- Schema validation — YAML parses correctly, references valid tables
- Metric existence check — all agent-referenced metrics exist in semantic views
- Test coverage minimum — at least 3 test cases per metric
- No PII exposure — metric definitions don’t expose PII without masking policies
STAGING → PRODUCTION (mixed): 5. Full test suite pass (automated) 6. Smoke test with production data (automated) 7. Domain steward approval (manual) 8. Compliance review (manual) 9. Breaking change 7-day window (SLA check) 10. Rollback plan documented (manual, warn-only)
CREATE OR REPLACE TABLE governance.devops.promotion_gates (
from_environment VARCHAR NOT NULL,
to_environment VARCHAR NOT NULL,
gate_name VARCHAR NOT NULL,
gate_type VARCHAR NOT NULL, -- automated, manual_approval, sla_check
failure_action VARCHAR NOT NULL, -- BLOCK, WARN, NOTIFY
applies_to_asset_types ARRAY
);
The critical design choice: BLOCK, not WARN. If a gate can be bypassed, it will be. Automated gates that block promotion eliminate the “just this once” failure mode that erodes governance over time.
Change Tracking
Every change — creation, modification, promotion, rollback — is recorded with full context:
CREATE OR REPLACE TABLE governance.devops.change_log (
change_id VARCHAR DEFAULT UUID_STRING(),
asset_type VARCHAR NOT NULL,
asset_fqn VARCHAR NOT NULL,
change_type VARCHAR NOT NULL,
git_commit_sha VARCHAR,
git_branch VARCHAR,
yaml_before TEXT, -- For rollback
yaml_after TEXT,
requested_by VARCHAR NOT NULL,
approved_by ARRAY,
is_breaking_change BOOLEAN DEFAULT FALSE,
impact_assessment TEXT,
status VARCHAR DEFAULT 'PENDING'
);
This table is the backbone of SOX compliance evidence. Every promotion has a requester, an approver (different person), a Git commit, and a before/after diff.
Automated Validation Engine
Gates aren’t just documentation — they’re enforced programmatically. The validation suite runs before any promotion and returns pass/fail with specific errors:
CREATE OR REPLACE PROCEDURE governance.devops.run_validation_suite(
P_ASSET_FQN VARCHAR,
P_ASSET_TYPE VARCHAR,
P_TARGET_ENV VARCHAR
)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
DECLARE
v_results ARRAY DEFAULT ARRAY_CONSTRUCT();
v_all_pass BOOLEAN DEFAULT TRUE;
v_from_env VARCHAR;
v_naming_valid BOOLEAN;
v_has_owner BOOLEAN;
v_metric_count INTEGER;
BEGIN
v_from_env := CASE WHEN :P_TARGET_ENV = 'STAGING' THEN 'DEV'
WHEN :P_TARGET_ENV = 'PRODUCTION' THEN 'STAGING'
ELSE 'UNKNOWN' END;
-- Gate 1: Naming convention check
v_naming_valid := CASE
WHEN :P_ASSET_TYPE = 'semantic_view' AND REGEXP_LIKE(:P_ASSET_FQN, '.*\\.[a-z]+_[a-z]+.*') THEN TRUE
WHEN :P_ASSET_TYPE = 'agent' AND REGEXP_LIKE(:P_ASSET_FQN, '.*[a-z]+_(agent|assistant)$') THEN TRUE
ELSE FALSE
END;
IF (NOT v_naming_valid) THEN
v_all_pass := FALSE;
END IF;
v_results := ARRAY_APPEND(:v_results, OBJECT_CONSTRUCT(
'gate', 'Naming Convention',
'status', CASE WHEN :v_naming_valid THEN 'PASS' ELSE 'FAIL' END,
'detail', CASE WHEN :v_naming_valid THEN 'Naming convention validated'
ELSE 'Asset name does not match pattern for ' || :P_ASSET_TYPE END
));
-- Gate 2: Ownership check
v_has_owner := (
SELECT COUNT(*) = 0 FROM governance.operating_model.metric_catalog
WHERE semantic_view_fqn = :P_ASSET_FQN
AND (owner_role IS NULL OR steward_role IS NULL)
);
IF (NOT v_has_owner) THEN
v_all_pass := FALSE;
END IF;
v_results := ARRAY_APPEND(:v_results, OBJECT_CONSTRUCT(
'gate', 'Ownership Coverage',
'status', CASE WHEN :v_has_owner THEN 'PASS' ELSE 'FAIL' END,
'detail', CASE WHEN :v_has_owner THEN 'All metrics have owner and steward assigned'
ELSE 'Some metrics missing owner_role or steward_role' END
));
-- Gate 3: Metric registration
v_metric_count := (
SELECT COUNT(*) FROM governance.operating_model.metric_catalog
WHERE semantic_view_fqn = :P_ASSET_FQN
);
IF (v_metric_count = 0 AND :P_ASSET_TYPE = 'semantic_view') THEN
v_all_pass := FALSE;
END IF;
v_results := ARRAY_APPEND(:v_results, OBJECT_CONSTRUCT(
'gate', 'Metric Registration',
'status', CASE WHEN :v_metric_count > 0 OR :P_ASSET_TYPE != 'semantic_view' THEN 'PASS' ELSE 'FAIL' END,
'detail', 'Metrics registered: ' || :v_metric_count
));
-- Gate 4: For PRODUCTION, require certified metrics
IF (:P_TARGET_ENV = 'PRODUCTION') THEN
LET uncertified INTEGER := (
SELECT COUNT(*) FROM governance.operating_model.metric_catalog
WHERE semantic_view_fqn = :P_ASSET_FQN
AND certification_status NOT IN ('CERTIFIED', 'PENDING')
);
IF (uncertified > 0) THEN
v_all_pass := FALSE;
END IF;
v_results := ARRAY_APPEND(:v_results, OBJECT_CONSTRUCT(
'gate', 'Certification Status',
'status', CASE WHEN uncertified = 0 THEN 'PASS' ELSE 'FAIL' END,
'detail', CASE WHEN uncertified = 0 THEN 'All metrics certified or pending'
ELSE uncertified || ' metrics not yet certified' END
));
END IF;
RETURN OBJECT_CONSTRUCT(
'asset_fqn', :P_ASSET_FQN,
'target_environment', :P_TARGET_ENV,
'overall_status', CASE WHEN :v_all_pass THEN 'PASS' ELSE 'FAIL' END,
'gates_evaluated', ARRAY_SIZE(:v_results),
'results', :v_results,
'action', CASE WHEN :v_all_pass THEN 'Ready for promotion'
ELSE 'Fix failures before promoting' END
);
END;
$$;
Automated Promotion
If all gates pass, promotion happens without waiting for a human to click “deploy”:
CREATE OR REPLACE PROCEDURE governance.devops.promote_asset(
P_ASSET_FQN VARCHAR,
P_ASSET_TYPE VARCHAR,
P_TARGET_ENV VARCHAR,
P_GIT_SHA VARCHAR,
P_DESCRIPTION VARCHAR
)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
DECLARE
v_validation VARIANT;
v_from_env VARCHAR;
BEGIN
-- Run validation suite first
CALL governance.devops.run_validation_suite(:P_ASSET_FQN, :P_ASSET_TYPE, :P_TARGET_ENV);
v_validation := (SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())));
-- Block if validation fails
IF (v_validation:overall_status::VARCHAR != 'PASS') THEN
RETURN OBJECT_CONSTRUCT(
'status', 'BLOCKED',
'reason', 'Validation gates failed. Fix issues before promoting.',
'validation_results', :v_validation
);
END IF;
v_from_env := CASE WHEN :P_TARGET_ENV = 'STAGING' THEN 'DEV'
WHEN :P_TARGET_ENV = 'PRODUCTION' THEN 'STAGING' END;
-- Log the promotion
INSERT INTO governance.devops.change_log
(asset_type, asset_fqn, change_type, source_environment, target_environment,
git_commit_sha, change_description, requested_by, approved_by,
approval_timestamp, is_breaking_change, status)
SELECT :P_ASSET_TYPE, :P_ASSET_FQN, 'promote', :v_from_env, :P_TARGET_ENV,
:P_GIT_SHA, :P_DESCRIPTION, CURRENT_USER(),
ARRAY_CONSTRUCT(CURRENT_USER()), CURRENT_TIMESTAMP(), FALSE, 'DEPLOYED';
RETURN OBJECT_CONSTRUCT(
'status', 'SUCCESS',
'asset_fqn', :P_ASSET_FQN,
'promoted_to', :P_TARGET_ENV,
'git_sha', :P_GIT_SHA,
'validation', :v_validation
);
END;
$$;
Compliance Automation
Regulatory compliance isn’t a separate workstream — it’s a property of the governance model. If you build the operating model correctly, compliance evidence generates itself.
Regulatory Mapping
Each regulation maps to specific controls already built into the system:
| Regulation | Section | Requirement | Governance Control |
| ---------- | ------------ | --------------------------------------- | ------------------------------------------------- |
| SOX | 302 | Financial reports accurate and complete | Metric certification + quarterly recertification |
| SOX | 404 | Internal controls effective | Change log + promotion gates + audit trail |
| SOX | 404 | Change management | DevOps pipeline with 7-day breaking-change window |
| SOX | 404 | Segregation of duties | RACI matrix: requester ≠ approver |
| GDPR | Art. 5(1)(b) | Purpose limitation | Agent boundary rules + domain-scoped views |
| GDPR | Art. 5(1)(c) | Data minimisation | Semantic views expose aggregates only |
| GDPR | Art. 13/14 | Transparency | Agent provenance disclosure + audit log |
| GDPR | Art. 22 | Automated decision-making | Escalation protocol + human-in-the-loop |
| HIPAA | 164.502 | Minimum necessary standard | Row access + column masking + role scoping |
| HIPAA | 164.312 | Audit controls | Complete interaction trace in audit log |
| EU AI Act | Art. 13 | Transparency | Grounded inference with provenance |
| EU AI Act | Art. 14 | Human oversight | Escalation + suspension capability |
| EU AI Act | Art. 9 | Risk management | Monitoring KPIs + drift detection |
Table : Regulatory mapping showing how semantic layer governance controls align with SOX, GDPR, HIPAA, and EU AI Act compliance requirements.
Evidence Generation
Instead of scrambling before audit season, compliance evidence is generated automatically:
CREATE OR REPLACE PROCEDURE governance.compliance.generate_sox_evidence(P_QUARTER VARCHAR)
RETURNS TABLE()
LANGUAGE SQL
AS
$$
BEGIN
LET res RESULTSET := (
WITH change_control_evidence AS (
SELECT
'Change Management'::VARCHAR AS control_area,
'Promotion records'::VARCHAR AS evidence_type,
('Total promotions: ' || COUNT(*) || ', Approved: ' ||
SUM(CASE WHEN status = 'DEPLOYED' THEN 1 ELSE 0 END))::VARCHAR AS finding,
(CASE WHEN SUM(CASE WHEN status = 'DEPLOYED' AND ARRAY_SIZE(approved_by) = 0 THEN 1 ELSE 0 END) = 0
THEN 'COMPLIANT' ELSE 'NON-COMPLIANT' END)::VARCHAR AS status
FROM governance.devops.change_log
WHERE deployed_at >= DATEADD('quarter', -1, CURRENT_TIMESTAMP())
),
segregation_evidence AS (
SELECT
'Segregation of Duties'::VARCHAR AS control_area,
'Approval separation'::VARCHAR AS evidence_type,
('Changes where requester != approver: ' || COUNT(*))::VARCHAR AS finding,
(CASE WHEN COUNT(CASE WHEN requested_by = approved_by[0]::VARCHAR THEN 1 END) = 0
THEN 'COMPLIANT' ELSE 'FINDING' END)::VARCHAR AS status
FROM governance.devops.change_log
WHERE deployed_at >= DATEADD('quarter', -1, CURRENT_TIMESTAMP())
AND status = 'DEPLOYED'
)
SELECT * FROM change_control_evidence
UNION ALL
SELECT * FROM segregation_evidence
);
RETURN TABLE(res);
END;
$$;
Call this procedure once per quarter and you have audit-ready evidence for SOX 404 change management and segregation of duties — automatically, from the same data that powers your governance operations.
Scaling Patterns: From 10 Metrics to 10,000
Not every organization needs the full enterprise operating model on day one. The governance approach should match the scale:
Stage 1: Foundation (1–50 metrics, 1–3 domains)
- Team: 1 platform engineer + domain stewards (part-time)
- Cadence: Monthly governance meeting
- Tools: Manual YAML authoring, manual testing
- Risk: Low. Direct communication still works.
Stage 2: Growth (50–500 metrics, 4–10 domains)
- Team: 3–5 platform engineers + dedicated domain stewards
- Cadence: Bi-weekly governance + weekly standups
- Tools: CI/CD pipeline, automated testing, staging environment
- Risk: Medium. Naming conflicts and ownership gaps emerge.
Stage 3: Scale (500–5,000 metrics, 10–30 domains)
- Team: Dedicated platform team (8–12) + domain pods
- Cadence: Continuous governance with automated gates
- Tools: Full DevOps, automated recertification, self-service onboarding
- Risk: High. Without automation, governance becomes a bottleneck.
Stage 4: Enterprise (5,000+ metrics, 30+ domains)
- Team: Federated model with central platform + domain teams
- Cadence: Autonomous within guardrails, exception-based escalation
- Tools: Policy-as-code, ML-based drift detection, auto-deprecation
- Risk: Very high. Federated ownership must be rigidly enforced.
The key insight: the governance process must scale faster than the metrics. If adding one metric requires a meeting, you’ll have shadow metrics within 6 months. Self-service with guardrails — not gatekeeping — is the answer.
Self-Service Metric Requests
At scale, new metric requests flow through a queue, not a meeting:
CREATE OR REPLACE TABLE governance.operating_model.metric_requests (
request_id VARCHAR DEFAULT UUID_STRING(),
requested_by VARCHAR NOT NULL,
domain VARCHAR NOT NULL,
metric_name VARCHAR NOT NULL,
business_justification TEXT NOT NULL,
proposed_definition TEXT NOT NULL,
urgency VARCHAR DEFAULT 'STANDARD',
status VARCHAR DEFAULT 'SUBMITTED',
assigned_to VARCHAR,
submitted_at TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP(),
sla_deadline TIMESTAMP_NTZ
);
Standard requests have a 72-hour SLA. Expedited requests have 24 hours. If the SLA is breached, it escalates automatically. This eliminates the “governance is slow so I’ll build my own” failure mode.
Self-Service Onboarding Automation
The governance model fails if onboarding a new domain takes months. We provide stored procedures that let domain teams onboard themselves within guardrails — the platform team doesn’t touch anything unless a gate fails.
Domain Onboarding: One Procedure Call
CREATE OR REPLACE PROCEDURE governance.operating_model.onboard_domain(
P_DOMAIN_NAME VARCHAR,
P_DESCRIPTION VARCHAR,
P_STEWARD_USER VARCHAR,
P_BACKUP_STEWARD VARCHAR
)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
DECLARE
v_role_name VARCHAR;
v_result VARIANT;
BEGIN
-- Validate naming convention
IF (NOT REGEXP_LIKE(:P_DOMAIN_NAME, '^[A-Za-z][A-Za-z0-9_ ]+$')) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Domain name must start with a letter and contain only alphanumeric characters, spaces, or underscores.'
);
END IF;
-- Check if domain already exists
LET domain_exists INTEGER := (
SELECT COUNT(*) FROM governance.operating_model.domain_registry
WHERE UPPER(domain_name) = UPPER(:P_DOMAIN_NAME)
);
IF (domain_exists > 0) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Domain already registered: ' || :P_DOMAIN_NAME
);
END IF;
-- Create the domain steward role
v_role_name := 'DOMAIN_STEWARD_' || UPPER(REPLACE(:P_DOMAIN_NAME, ' ', '_'));
EXECUTE IMMEDIATE 'CREATE ROLE IF NOT EXISTS ' || :v_role_name;
EXECUTE IMMEDIATE 'GRANT ROLE ' || :v_role_name || ' TO ROLE governance_council_admin';
EXECUTE IMMEDIATE 'GRANT ROLE metric_consumer_full TO ROLE ' || :v_role_name;
-- Register in domain_registry
INSERT INTO governance.operating_model.domain_registry
(domain_name, domain_description, steward_role, steward_user, backup_steward,
governance_maturity, next_review_due)
VALUES (:P_DOMAIN_NAME, :P_DESCRIPTION, :v_role_name, :P_STEWARD_USER, :P_BACKUP_STEWARD,
'FOUNDATION', DATEADD('month', 1, CURRENT_DATE()));
-- Log the onboarding event
INSERT INTO governance.devops.change_log
(asset_type, asset_fqn, change_type, source_environment, change_description,
requested_by, approved_by, status)
SELECT 'domain', :P_DOMAIN_NAME, 'create', 'PRODUCTION',
'Self-service domain onboarding: ' || :P_DOMAIN_NAME,
CURRENT_USER(), ARRAY_CONSTRUCT(CURRENT_USER()), 'DEPLOYED';
RETURN OBJECT_CONSTRUCT(
'status', 'SUCCESS',
'domain', :P_DOMAIN_NAME,
'steward_role', :v_role_name,
'steward_user', :P_STEWARD_USER,
'next_steps', ARRAY_CONSTRUCT(
'Define 3-5 initial metrics using governance.operating_model.register_metric()',
'Create semantic view YAML in DEV environment',
'Run CALL governance.devops.promote_asset() to move through pipeline'
)
);
END;
$$;
Usage:
CALL governance.operating_model.onboard_domain(
'Data Science', 'ML features, model metrics, experiment tracking',
'DS_LEAD_CHEN', 'ML_ENG_PATEL'
);
-- Returns: {"status": "SUCCESS", "steward_role": "DOMAIN_STEWARD_DATA_SCIENCE", ...}
Metric Registration with Validation
CREATE OR REPLACE PROCEDURE governance.operating_model.register_metric(
P_DOMAIN VARCHAR,
P_METRIC_NAME VARCHAR,
P_BUSINESS_DEFINITION VARCHAR,
P_SEMANTIC_VIEW_FQN VARCHAR,
P_DATA_TYPE VARCHAR,
P_AGGREGATION VARCHAR,
P_TIME_GRAIN VARCHAR,
P_FRESHNESS_SLA_HOURS INTEGER
)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
DECLARE
v_metric_fqn VARCHAR;
v_steward_role VARCHAR;
BEGIN
-- Validate metric naming convention
IF (NOT REGEXP_LIKE(:P_METRIC_NAME, '^[a-z][a-z0-9_]{2,50}$')) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Metric name must be lowercase, start with letter, 3-51 chars. Got: ' || :P_METRIC_NAME
);
END IF;
-- Validate domain exists
LET domain_exists INTEGER := (
SELECT COUNT(*) FROM governance.operating_model.domain_registry
WHERE domain_name = :P_DOMAIN AND is_active = TRUE
);
IF (domain_exists = 0) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Domain not found or inactive: ' || :P_DOMAIN || '. Register domain first.'
);
END IF;
-- Check for duplicate metric name within domain
LET metric_exists INTEGER := (
SELECT COUNT(*) FROM governance.operating_model.metric_catalog
WHERE domain = :P_DOMAIN AND metric_name = :P_METRIC_NAME
);
IF (metric_exists > 0) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Metric already exists in domain: ' || :P_DOMAIN || '.' || :P_METRIC_NAME
);
END IF;
-- Build FQN and register as DRAFT
v_metric_fqn := LOWER(REPLACE(:P_DOMAIN, ' ', '_')) || '.semantic.' || :P_METRIC_NAME;
v_steward_role := (SELECT steward_role FROM governance.operating_model.domain_registry WHERE domain_name = :P_DOMAIN);
INSERT INTO governance.operating_model.metric_catalog
(metric_fqn, domain, metric_name, business_definition, semantic_view_fqn,
data_type, aggregation_method, time_grain, owner_role, steward_role,
certification_status, freshness_sla_hours)
VALUES (:v_metric_fqn, :P_DOMAIN, :P_METRIC_NAME, :P_BUSINESS_DEFINITION,
:P_SEMANTIC_VIEW_FQN, :P_DATA_TYPE, :P_AGGREGATION, :P_TIME_GRAIN,
CURRENT_ROLE(), :v_steward_role, 'DRAFT', :P_FRESHNESS_SLA_HOURS);
-- Update domain metric count
UPDATE governance.operating_model.domain_registry
SET metric_count = metric_count + 1
WHERE domain_name = :P_DOMAIN;
RETURN OBJECT_CONSTRUCT(
'status', 'SUCCESS',
'metric_fqn', :v_metric_fqn,
'certification_status', 'DRAFT',
'next_steps', ARRAY_CONSTRUCT(
'Add metric to semantic view YAML',
'Write 3 test cases (resolution, disambiguation, boundary)',
'Run CALL governance.operating_model.certify_metric() when ready'
)
);
END;
$$;
Metric Certification with Quality Enforcement
CREATE OR REPLACE PROCEDURE governance.operating_model.certify_metric(
P_METRIC_FQN VARCHAR,
P_DATA_QUALITY_SCORE NUMBER,
P_APPROVER VARCHAR
)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
DECLARE
v_current_status VARCHAR;
v_domain VARCHAR;
BEGIN
v_current_status := (SELECT certification_status FROM governance.operating_model.metric_catalog WHERE metric_fqn = :P_METRIC_FQN);
v_domain := (SELECT domain FROM governance.operating_model.metric_catalog WHERE metric_fqn = :P_METRIC_FQN);
IF (v_current_status IS NULL) THEN
RETURN OBJECT_CONSTRUCT('status', 'FAILED', 'error', 'Metric not found: ' || :P_METRIC_FQN);
END IF;
-- Validate quality threshold (must be >= 95%)
IF (:P_DATA_QUALITY_SCORE < 95.0) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Data quality score must be >= 95.0 for certification. Got: ' || :P_DATA_QUALITY_SCORE,
'recommendation', 'Investigate and fix data quality issues before certifying.'
);
END IF;
-- Validate segregation of duties
IF (:P_APPROVER = CURRENT_USER()) THEN
RETURN OBJECT_CONSTRUCT(
'status', 'FAILED',
'error', 'Segregation of duties violation: approver cannot be the same as requester.',
'recommendation', 'Ask your domain steward to approve.'
);
END IF;
-- Certify the metric
UPDATE governance.operating_model.metric_catalog
SET certification_status = 'CERTIFIED',
certification_date = CURRENT_DATE(),
recertification_due = DATEADD('day', 90, CURRENT_DATE()),
data_quality_score = :P_DATA_QUALITY_SCORE,
updated_at = CURRENT_TIMESTAMP()
WHERE metric_fqn = :P_METRIC_FQN;
-- Update domain certification rate
UPDATE governance.operating_model.domain_registry
SET certification_rate = (
SELECT ROUND(COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 1)
FROM governance.operating_model.metric_catalog WHERE domain = :v_domain
)
WHERE domain_name = :v_domain;
-- Log the certification
INSERT INTO governance.devops.change_log
(asset_type, asset_fqn, change_type, source_environment, change_description,
requested_by, approved_by, status)
SELECT 'metric', :P_METRIC_FQN, 'certify', 'PRODUCTION',
'Metric certified with quality score ' || :P_DATA_QUALITY_SCORE,
CURRENT_USER(), ARRAY_CONSTRUCT(:P_APPROVER), 'DEPLOYED';
RETURN OBJECT_CONSTRUCT(
'status', 'SUCCESS',
'metric_fqn', :P_METRIC_FQN,
'certification_status', 'CERTIFIED',
'recertification_due', DATEADD('day', 90, CURRENT_DATE())::VARCHAR,
'data_quality_score', :P_DATA_QUALITY_SCORE
);
END;
$$;
Operating Cadences
Governance without rhythm becomes governance without action. The operating model defines 9 cadences across 5 frequencies:
Daily (Automated)
- Agent Health Check — grounding rate, confidence, error rate, latency. Alert if grounding < 90% or confidence < 70%.
- Data Quality Monitor — freshness and quality checks on all source tables. Auto-degrade agents if critical.
Weekly (30 min each)
- Semantic Signals Triage — review agent escalations, low-confidence queries, disambiguation failures. Output: new metric requests and disambiguation rule updates.
- Pipeline Review — pending promotions, change requests, deployment schedule.
Monthly (60 min each)
- Domain Health Review — per-domain certification currency, usage trends, quality scores. Flag domains below 80% certification rate.
- Compliance Checkpoint — validate all regulatory controls functioning, evidence current.
Quarterly (120 min)
- Governance Council — strategic review with CDO, all domain stewards, platform lead, compliance. Policy changes, role assignments, investment priorities.
- Recertification Cycle — all certified metrics reviewed and re-affirmed. Auto-decertify if not completed within 7-day grace period.
Annual (240 min)
- Operating Model Review — full assessment of governance effectiveness, role reassignment, process improvements.
Full Automation: The Self-Running Governance Machine
The daily cadences aren’t just meetings — they’re a Task DAG that runs without human intervention:
-- Root task: runs daily at 5 AM
CREATE TASK IF NOT EXISTS governance.operating_model.task_governance_daily_root
WAREHOUSE = COMPUTE_WH
SCHEDULE = 'USING CRON 0 5 * * * America/Los_Angeles'
AS SELECT 1;
-- Child 1: Refresh usage stats (must run first)
CREATE OR REPLACE TASK governance.operating_model.task_daily_refresh_usage
WAREHOUSE = COMPUTE_WH
AFTER governance.operating_model.task_governance_daily_root
AS CALL governance.operating_model.refresh_usage_stats();
-- Child 2: Auto-recertify high-confidence metrics
CREATE OR REPLACE TASK governance.operating_model.task_daily_auto_recertify
WAREHOUSE = COMPUTE_WH
AFTER governance.operating_model.task_daily_refresh_usage
AS CALL governance.operating_model.auto_recertify();
-- Child 3: Auto-decertify expired metrics
CREATE OR REPLACE TASK governance.operating_model.task_daily_auto_decertify
WAREHOUSE = COMPUTE_WH
AFTER governance.operating_model.task_daily_auto_recertify
AS CALL governance.operating_model.auto_decertify_expired();
-- Child 4: Recalculate domain maturity
CREATE OR REPLACE TASK governance.operating_model.task_daily_recalc_maturity
WAREHOUSE = COMPUTE_WH
AFTER governance.operating_model.task_daily_auto_decertify
AS CALL governance.operating_model.recalculate_domain_maturity();
-- Child 5: Evaluate and fire alerts
CREATE OR REPLACE TASK governance.operating_model.task_daily_evaluate_alerts
WAREHOUSE = COMPUTE_WH
AFTER governance.operating_model.task_daily_recalc_maturity
AS CALL governance.operating_model.evaluate_alerts();
Auto-Recertification (No Human Needed for High-Confidence Metrics)
CREATE OR REPLACE PROCEDURE governance.operating_model.auto_recertify()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
v_recertified INTEGER DEFAULT 0;
BEGIN
-- Auto-recertify metrics that:
-- 1. Are due for recertification within 7 days
-- 2. Have data_quality_score >= 98 (high confidence)
-- 3. Have been actively queried (query_count_30d > 100)
-- 4. Have no associated incidents in the past 90 days
UPDATE governance.operating_model.metric_catalog mc
SET certification_status = 'CERTIFIED',
certification_date = CURRENT_DATE(),
recertification_due = DATEADD('day', 90, CURRENT_DATE()),
updated_at = CURRENT_TIMESTAMP()
WHERE mc.certification_status = 'CERTIFIED'
AND mc.recertification_due BETWEEN CURRENT_DATE() AND DATEADD('day', 7, CURRENT_DATE())
AND mc.data_quality_score >= 98.0
AND mc.query_count_30d >= 100
AND NOT EXISTS (
SELECT 1 FROM governance.operating_model.incident_log il
WHERE ARRAY_CONTAINS(mc.metric_name::VARIANT, il.affected_metrics)
AND il.detected_at >= DATEADD('day', -90, CURRENT_TIMESTAMP())
);
v_recertified := SQLROWCOUNT;
RETURN 'Auto-recertified ' || :v_recertified || ' high-confidence metrics';
END;
$$;
Auto-Deprecation (Unused Metrics Self-Clean)
CREATE OR REPLACE PROCEDURE governance.operating_model.auto_deprecate_unused()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
v_deprecated INTEGER DEFAULT 0;
BEGIN
UPDATE governance.operating_model.metric_catalog
SET certification_status = 'DEPRECATED',
tags = ARRAY_APPEND(COALESCE(tags, ARRAY_CONSTRUCT()), 'AUTO_DEPRECATED'),
updated_at = CURRENT_TIMESTAMP()
WHERE certification_status IN ('EXPIRED', 'DRAFT')
AND (last_queried_at IS NULL OR last_queried_at < DATEADD('day', -180, CURRENT_TIMESTAMP()))
AND query_count_30d = 0
AND NOT ARRAY_CONTAINS('AUTO_DEPRECATED'::VARIANT, COALESCE(tags, ARRAY_CONSTRUCT()));
v_deprecated := SQLROWCOUNT;
RETURN 'Auto-deprecated ' || :v_deprecated || ' unused metrics (180+ days inactive)';
END;
$$;
Production Usage Stats from QUERY_HISTORY
CREATE OR REPLACE PROCEDURE governance.operating_model.refresh_usage_stats_v2()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
v_updated INTEGER DEFAULT 0;
BEGIN
MERGE INTO governance.operating_model.metric_catalog AS target
USING (
SELECT
mc.metric_fqn,
COUNT(DISTINCT qh.query_id) AS query_count,
COUNT(DISTINCT qh.user_name) AS consumer_count,
MAX(qh.start_time) AS last_queried
FROM governance.operating_model.metric_catalog mc
INNER JOIN snowflake.account_usage.query_history qh
ON CONTAINS(LOWER(qh.query_text), LOWER(mc.semantic_view_fqn))
AND qh.start_time >= DATEADD('day', -30, CURRENT_TIMESTAMP())
AND qh.execution_status = 'SUCCESS'
GROUP BY mc.metric_fqn
) AS source
ON target.metric_fqn = source.metric_fqn
WHEN MATCHED THEN UPDATE SET
target.query_count_30d = source.query_count,
target.consumer_count_30d = source.consumer_count,
target.last_queried_at = source.last_queried,
target.updated_at = CURRENT_TIMESTAMP();
v_updated := SQLROWCOUNT;
RETURN 'Updated usage stats for ' || :v_updated || ' metrics from QUERY_HISTORY';
END;
$$;
Auto-Recalculate Domain Maturity
CREATE OR REPLACE PROCEDURE governance.operating_model.recalculate_domain_maturity()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
BEGIN
UPDATE governance.operating_model.domain_registry dr
SET
certification_rate = COALESCE((
SELECT ROUND(COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 1)
FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name
), 0),
avg_data_quality = (
SELECT AVG(data_quality_score)
FROM governance.operating_model.metric_catalog
WHERE domain = dr.domain_name AND data_quality_score IS NOT NULL
),
metric_count = (
SELECT COUNT(*) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name
),
governance_maturity = CASE
WHEN COALESCE((SELECT ROUND(COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 1) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name), 0) >= 90
AND COALESCE((SELECT AVG(data_quality_score) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name AND data_quality_score IS NOT NULL), 0) >= 95
AND dr.agent_count >= 2
THEN 'ENTERPRISE'
WHEN COALESCE((SELECT ROUND(COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 1) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name), 0) >= 80
AND COALESCE((SELECT AVG(data_quality_score) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name AND data_quality_score IS NOT NULL), 0) >= 90
THEN 'SCALE'
WHEN COALESCE((SELECT ROUND(COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 1) FROM governance.operating_model.metric_catalog WHERE domain = dr.domain_name), 0) >= 60
THEN 'GROWTH'
ELSE 'FOUNDATION'
END
WHERE dr.is_active = TRUE;
RETURN 'Domain maturity recalculated for all active domains';
END;
$$;
Alerting & Notification
Governance events trigger automated alerts — not emails someone ignores, but actionable notifications with specific escalation paths:
CREATE OR REPLACE TABLE governance.operating_model.alert_rules (
rule_id VARCHAR DEFAULT UUID_STRING(),
rule_name VARCHAR NOT NULL,
severity VARCHAR NOT NULL, -- CRITICAL, WARNING, INFO
condition_query TEXT NOT NULL, -- SQL that returns rows when alert should fire
notification_channel VARCHAR NOT NULL, -- email, slack_webhook
recipients ARRAY NOT NULL,
cooldown_hours INTEGER DEFAULT 24, -- Don't re-alert within this window
last_fired TIMESTAMP_NTZ,
is_active BOOLEAN DEFAULT TRUE
);
Production Alert Rules
| Rule | Severity | Cooldown | Trigger |
| ------------------------- | -------- | -------- | ------------------------------------ |
| Certification Below 80% | WARNING | 24h | Metric catalog drops below threshold |
| SEV-1 Incident Opened | CRITICAL | 1h | New severity-1 incident detected |
| Metric Expired | WARNING | 24h | Auto-decertification fired |
| Promotion Gate Failure | INFO | 4h | Asset blocked by validation |
| Domain Review Overdue | WARNING | 168h | Review date passed |
| High Rollback Rate (>15%) | CRITICAL | 24h | Too many deployments failing |
Table : Governance monitoring and alerting rules used to proactively detect certification drift, operational incidents, review violations, deployment instability, and policy compliance issues.
CREATE OR REPLACE PROCEDURE governance.operating_model.evaluate_alerts()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
v_fired INTEGER DEFAULT 0;
v_rule_cursor CURSOR FOR
SELECT rule_id, rule_name, severity, condition_query, cooldown_hours, last_fired
FROM governance.operating_model.alert_rules
WHERE is_active = TRUE;
v_rule_id VARCHAR;
v_rule_name VARCHAR;
v_severity VARCHAR;
v_condition VARCHAR;
v_cooldown INTEGER;
v_last_fired TIMESTAMP_NTZ;
BEGIN
FOR record IN v_rule_cursor DO
v_rule_id := record.rule_id;
v_rule_name := record.rule_name;
v_cooldown := record.cooldown_hours;
v_last_fired := record.last_fired;
-- Check cooldown period
IF (v_last_fired IS NOT NULL AND
v_last_fired > DATEADD('hour', -1 * v_cooldown, CURRENT_TIMESTAMP())) THEN
CONTINUE;
END IF; -- In production: EXECUTE IMMEDIATE condition_query, check SQLROWCOUNT,
-- send notification via Snowflake notification integration
UPDATE governance.operating_model.alert_rules
SET last_fired = CURRENT_TIMESTAMP()
WHERE rule_id = :v_rule_id; v_fired := v_fired + 1;
END FOR; RETURN 'Evaluated alerts. Fired: ' || :v_fired;
END;
$$;-- Run alert evaluation every 15 minutes
CREATE TASK IF NOT EXISTS governance.operating_model.task_evaluate_alerts
WAREHOUSE = COMPUTE_WH
SCHEDULE = 'USING CRON */15 * * * * America/Los_Angeles'
AS CALL governance.operating_model.evaluate_alerts();
Governance Health Dashboard: Metrics About Metrics
You can’t improve what you don’t measure. The governance layer itself needs KPIs:
CREATE OR REPLACE VIEW governance.operating_model.governance_health_scorecard AS
WITH certification_stats AS (
SELECT
COUNT(*) AS total_metrics,
COUNT(CASE WHEN certification_status = 'CERTIFIED' THEN 1 END) AS certified,
COUNT(CASE WHEN recertification_due < CURRENT_DATE()
AND certification_status = 'CERTIFIED' THEN 1 END) AS overdue_recert
FROM governance.operating_model.metric_catalog
),
ownership_stats AS (
SELECT COUNT(*) AS total_metrics,
COUNT(CASE WHEN owner_role IS NOT NULL
AND steward_role IS NOT NULL THEN 1 END) AS fully_owned
FROM governance.operating_model.metric_catalog
WHERE certification_status != 'DEPRECATED'
)
SELECT
ROUND(c.certified * 100.0 / NULLIF(c.total_metrics, 0), 1)
AS certification_coverage_pct,
c.overdue_recert AS overdue_recertifications,
CASE
WHEN c.certified * 100.0 / NULLIF(c.total_metrics, 0) >= 90 THEN 'HEALTHY'
WHEN c.certified * 100.0 / NULLIF(c.total_metrics, 0) >= 70 THEN 'WARNING'
ELSE 'CRITICAL'
END AS certification_health,
ROUND(o.fully_owned * 100.0 / NULLIF(o.total_metrics, 0), 1)
AS ownership_coverage_pct
FROM certification_stats c
CROSS JOIN ownership_stats o;
Target KPIs:
| KPI | Healthy | Warning | Critical |
| ------------------------------------------ | -------- | --------- | --------- |
| Certification Coverage | ≥ 90% | 70–89% | < 70% |
| Ownership Coverage | ≥ 95% | 80–94% | < 80% |
| Agent Grounding Rate | ≥ 95% | 85–94% | < 85% |
| Change Velocity (Request → Production) | ≤ 5 days | 5–14 days | > 14 days |
| Incident Rate (per 1,000 Interactions) | ≤ 1 | 1–5 | > 5 |
| Rollback Rate | ≤ 5% | 5–15% | > 15% |
| Recertification Currency | ≥ 95% | 80–94% | < 80% |
| Zombie Metrics (Certified, Unused 60 Days) | ≤ 5 | 5–20 | > 20 |
Table : Governance health scorecard defining operational thresholds for semantic layer quality, agent reliability, certification maturity, deployment effectiveness, and overall governance performance.
Incident Management
When an AI agent reports the wrong number in a board meeting, you need a response protocol — not a meeting to discuss having a meeting.
Severity Levels
| Severity | Description | Response SLA | Example |
| -------- | ---------------------------------------------- | ------------ | ------------------------------------------------ |
| SEV-1 | Wrong number in executive/board report | 4 hours | CFO quotes incorrect revenue in earnings call |
| SEV-2 | Agent consistently returning incorrect answers | 8 hours | Finance agent off by 15% on ARR for all users |
| SEV-3 | Metric definition dispute between domains | 48 hours | Sales and Finance disagree on "bookings" meaning |
| SEV-4 | Stale data beyond SLA threshold | 24 hours | Revenue data 48 hours old against 4-hour SLA |
Table : Incident severity classification matrix defining governance response priorities, remediation timelines, and escalation examples for semantic layer and AI agent operations.
SEV-1 response protocol:
- Immediately suspend the affected agent (automated if detected by monitoring)
- Notify all affected consumers within 1 hour
- Identify root cause within 4 hours
- Restore correct behavior or confirm suspension
- Post-mortem within 72 hours with preventive action
CREATE OR REPLACE TABLE governance.operating_model.incident_log (
incident_id VARCHAR DEFAULT UUID_STRING(),
severity INTEGER NOT NULL,
incident_type VARCHAR NOT NULL,
affected_metrics ARRAY,
affected_agents ARRAY,
detected_by VARCHAR NOT NULL, -- monitoring, user_report, audit
time_to_detect_minutes INTEGER,
time_to_mitigate_minutes INTEGER,
time_to_resolve_minutes INTEGER,
root_cause TEXT,
preventive_action TEXT,
agent_suspended BOOLEAN DEFAULT FALSE
);
Federated Governance at Scale
At 10,000+ people, centralized governance becomes a bottleneck. The solution is federated governance with central guardrails.
Central Team Owns:
- Platform infrastructure, pipelines, tooling
- Policy (naming conventions, quality thresholds, SLAs)
- Cross-domain conflict resolution
- Compliance mapping and audit evidence
- Agent platform (deployment, monitoring, escalation infrastructure)
Domain Teams Own:
- Metric definitions within their domain
- Certification decisions for their metrics
- Agent instructions for domain-specific agents
- Test cases for their domain
- Consumer support and training
Non-Negotiable Guardrails (Enforced by Platform):
- Every metric must have exactly ONE owner and ONE steward
- Every semantic view must pass schema validation
- Every agent must have boundary rules and escalation paths
- Every change must go through the promotion pipeline
- Every metric must be recertified quarterly
- Cross-domain terms must be registered in the business glossary
- Breaking changes require 7-day notice window
The Business Glossary
The most common failure mode in a federated model: two domains define the same term differently without knowing it. The business glossary prevents this:
CREATE OR REPLACE TABLE governance.operating_model.business_glossary (
term VARCHAR NOT NULL UNIQUE,
canonical_definition TEXT NOT NULL,
domain_owner VARCHAR NOT NULL,
disambiguation_rules TEXT,
commonly_confused_with ARRAY,
is_cross_domain BOOLEAN DEFAULT FALSE
);
Sample entries:
| Term | Canonical Definition | Disambiguation Rule |
| --------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Revenue | Recognized revenue per ASC 606. All product lines. USD. | Default to ASC 606. "Run rate" → ARR. "Bookings" → redirect to Sales domain. |
| Active Customer | Login in trailing 90 days AND active contract. | Always use a 90-day activity window. "Paying customer" = active customer + contract_value > 0. |
| Pipeline | Weighted value of open opportunities in stages 2–5. | Default to current open pipeline. "Forecast" refers to weighted pipeline only. |
| Churn | Zero activity for 90+ days AND contract not renewed. | Always interpret as logo churn unless otherwise specified. "At risk" ≠ churned. |
Table : Canonical business glossary defining enterprise-standard metric definitions and disambiguation rules used by semantic views and AI agents to ensure consistent interpretation across domains.
Naming Conventions
At scale, naming conventions prevent the “Revenue_Table_Final_v2_FIXED” failure mode:
| Asset Type | Pattern | Valid Example | Invalid Example | Enforcement |
| ------------- | -------------------------- | ------------------ | --------------- | ----------- |
| Semantic View | domain_name(_v#)? | finance_revenue_v2 | RevenueMetrics | BLOCK |
| Metric | lowercase_3_to_51 | recognized_revenue | Rev $ | BLOCK |
| Agent | domain_(agent|assistant) | finance_agent | FinanceBot | BLOCK |
| Table | (fct|dim|agg|stg|raw)_name | fct_revenue | Revenue_Final | WARN |
Table : Naming convention standards enforced across semantic views, metrics, agents, and physical data assets to ensure consistency, discoverability, governance compliance, and automated validation.
BLOCK means the promotion pipeline rejects assets that don’t match the pattern. This is enforced automatically — not by code review, not by a style guide that nobody reads.
What Runs Without Human Intervention
| Frequency | What | How |
| --------------- | -------------------- | --------------------------------------------------------------------------- |
| Every 15 min | Alert evaluation | Checks 6 alert rules and fires notifications on threshold breaches |
| Daily 5:00 AM | Refresh usage stats | MERGE usage metrics from QUERY_HISTORY into metric_catalog |
| Daily 5:00 AM | Auto-recertify | Recertifies metrics with quality ≥ 98%, active usage, and no open incidents |
| Daily 5:00 AM | Auto-decertify | Decertifies metrics that exceed the 7-day grace period after expiration |
| Daily 5:00 AM | Recalculate maturity | Updates domain maturity scores based on current governance metrics |
| Daily 5:00 AM | Fire alerts | Generates notifications for governance health threshold violations |
| Weekly (Monday) | Flag zombies | Identifies certified metrics with zero queries for 60+ days |
| Weekly (Monday) | Auto-deprecate | Deprecates expired or draft metrics with no usage for 180+ days |
Table : Automated governance operations schedule showing recurring monitoring, certification, alerting, lifecycle management, and metric hygiene activities executed across the semantic layer platform.
On-demand self-service:
onboard_domain()— registers domain, creates role, logs eventregister_metric()— validates naming, creates DRAFT metriccertify_metric()— validates quality + segregation of duties, certifiespromote_asset()— runs validation suite, blocks or promotesrun_validation_suite()— programmatic gate evaluation
Humans only intervene for:
- Initial approval of new domains/agents (RACI sign-off)
- Resolving incidents (SLA-tracked)
- Quarterly governance council (strategic decisions)
- Breaking changes (7-day notice + 3 approvers)
Everything else is automated, monitored, and self-healing.
The Bottom Line
Technology scales infinitely. Governance scales only if you design it to.
The difference between a 50-metric semantic layer that works and a 5,000-metric semantic layer that works is not more technology. It’s operating model:
- Clear ownership — exactly one owner, one steward, per metric
- Fast process — self-service within guardrails, not gatekeeping
- Automated enforcement — promotion gates, not review meetings
- Federated responsibility — domain teams own, platform enables
- Continuous feedback — agent interactions become improvement signals
- Measured health — governance KPIs with the same rigor as product KPIs
- Self-healing — auto-recertify, auto-decertify, auto-deprecate without tickets
A semantic layer without an operating model is a documentation project. A semantic layer with an operating model is enterprise infrastructure. A semantic layer with an automated operating model is a competitive advantage.
Build the model. Automate it. Measure it. Let it run.
What’s Next
Part 5 will cover advanced patterns: multi-tenant semantic layers, real-time metrics, the semantic layer as API, and cross-cloud federation — extending Horizon Context beyond a single Snowflake account into the full enterprise topology.
The complete implementation code for this article is available in two companion SQL files in github:
Part 4 - Enterprise Governance and Operating Model.sql— infrastructure, tables, views, and data (1,473 lines)Part 4B - Full Governance Automation.sql— self-service procedures, validation engine, alerting, auto-remediation, and task DAG (832 lines)- Total: 2,305 lines of production-tested Snowflake SQL
Join thousands of data leaders on the AI newsletter. Join over 80,000 subscribers and keep up to date with the latest developments in AI. From research to projects and ideas. If you are building an AI startup, an AI-related product, or a service, we invite you to consider becoming a sponsor.
Published via Towards AI
Towards AI Academy
We Build Enterprise-Grade AI. We'll Teach You to Master It Too.
15 engineers. 100,000+ students. Towards AI Academy teaches what actually survives production.
Start free — no commitment:
→ 6-Day Agentic AI Engineering Email Guide — one practical lesson per day
→ Agents Architecture Cheatsheet — 3 years of architecture decisions in 6 pages
Our courses:
→ AI Engineering Certification — 90+ lessons from project selection to deployed product. The most comprehensive practical LLM course out there.
→ Agent Engineering Course — Hands on with production agent architectures, memory, routing, and eval frameworks — built from real enterprise engagements.
→ AI for Work — Understand, evaluate, and apply AI for complex work tasks.
Note: Article content contains the views of the contributing authors and not Towards AI.